home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / Ang261Lib.lha / src / moria2.c < prev    next >
C/C++ Source or Header  |  1994-10-22  |  89KB  |  3,131 lines

  1. /*
  2.  * moria2.c: misc code, mainly to handle player commands 
  3.  *
  4.  * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke 
  5.  *
  6.  * This software may be copied and distributed for educational, research, and
  7.  * not for profit purposes provided that this copyright and statement are
  8.  * included in all such copies. 
  9.  */
  10.  
  11. #include <ctype.h>
  12.  
  13. #include "constant.h"
  14. #include "monster.h"
  15. #include "config.h"
  16. #include "types.h"
  17. #include "externs.h"
  18.  
  19. #ifdef USG
  20. #ifndef ATARIST_MWC
  21. #include <string.h>
  22. #endif
  23. #else
  24. #include <strings.h>
  25. #endif
  26.  
  27. /* Lets do all prototypes correctly.... -CWS */
  28. #ifndef NO_LINT_ARGS
  29. #ifdef __STDC__
  30. static int look_ray(int, int, int);
  31. static int look_see(int, int, int *);
  32. static void hit_trap(int, int);
  33. static int summon_object(int, int, int, int, int32u);
  34. static void py_attack(int, int);
  35. static void chest_trap(int, int);
  36. static void inven_throw(int, struct inven_type *);
  37. static void facts(struct inven_type *, int *, int *, int *, int *, int *);
  38. static void drop_throw(int, int, struct inven_type *);
  39. static void py_bash(int, int);
  40. static const char *look_mon_desc(int);
  41. static int fearless(creature_type *);
  42.  
  43. #else
  44. static int look_ray();
  45. static int look_see();
  46. static void hit_trap();
  47. static int summon_object();
  48. static void py_attack();
  49. static void chest_trap();
  50. static void inven_throw();
  51. static void facts();
  52. static void drop_throw();
  53. static void py_bash();
  54. static const char *look_mon_desc();
  55. static int fearless();
  56.  
  57. #endif
  58. #endif
  59.  
  60.  
  61. /* Player hit a trap.    (Chuckle)            -RAK-     */
  62. static void 
  63. hit_trap(y, x)
  64. int y, x;
  65. {
  66.     int                   i, ty, tx, num, dam;
  67.     register cave_type   *c_ptr;
  68.     register struct misc *p_ptr;
  69.     register inven_type  *t_ptr;
  70.     bigvtype              tmp;
  71.  
  72.     end_find();
  73.     change_trap(y, x);
  74.     c_ptr = &cave[y][x];
  75.     p_ptr = &py.misc;
  76.     t_ptr = &t_list[c_ptr->tptr];
  77.     dam = pdamroll(t_ptr->damage);
  78.     switch (t_ptr->subval) {
  79.       case 1:               /* Open pit */
  80.     msg_print("You fell into a pit!");
  81.     if (py.flags.ffall)
  82.         msg_print("You gently float down.");
  83.     else {
  84.         objdes(tmp, t_ptr, TRUE);
  85.         take_hit(dam, tmp);
  86.     }
  87.     break;
  88.       case 2:               /* Arrow trap */
  89.     if (test_hit(125, 0, 0, p_ptr->pac + p_ptr->ptoac, CLA_MISC_HIT)) {
  90.         objdes(tmp, t_ptr, TRUE);
  91.         take_hit(dam, tmp);
  92.         msg_print("An arrow hits you.");
  93.     } else
  94.         msg_print("An arrow barely misses you.");
  95.     break;
  96.       case 3:               /* Covered pit */
  97.     msg_print("You fell into a covered pit.");
  98.     if (py.flags.ffall)
  99.         msg_print("You gently float down.");
  100.     else {
  101.         objdes(tmp, t_ptr, TRUE);
  102.         take_hit(dam, tmp);
  103.     }
  104.     place_trap(y, x, 0);
  105.     break;
  106.       case 4:               /* Trap door */
  107.     if (!is_quest(dun_level)) {/* that would be too easy... -CFT */
  108.         msg_print("You fell through a trap door!");
  109.         new_level_flag = TRUE;
  110.         dun_level++;
  111.         if (py.flags.ffall)
  112.         msg_print("You gently float down.");
  113.         else {
  114.         objdes(tmp, t_ptr, TRUE);
  115.         take_hit(dam, tmp);
  116.         }
  117.         msg_print(NULL);       /* make sure can see the message before new level */
  118.     }
  119.      /* end normal */ 
  120.     else {               /* it's a quest level, can't let them fall through */
  121.         msg_print("You fall into a spiked pit!");
  122.         if (py.flags.ffall)
  123.         msg_print("You gently float down.");
  124.         else {
  125.         dam = (dam * 3) / 2;    /* do a little extra damage for spikes */
  126.         if (randint(3) == 1) {
  127.             msg_print("The spikes are poisoned!");
  128.             if (!(py.flags.poison_im || py.flags.poison_resist ||
  129.               py.flags.resist_poison))
  130.             dam *= 2;  /* more damage from poison!  :-)  -CFT */
  131.             else
  132.             msg_print("You are unaffected by the poison.");
  133.         }
  134.         } /* no ffall */
  135.     }
  136.     break;
  137.       case 5:               /* Sleep gas */
  138.     if (py.flags.paralysis == 0) {
  139.         msg_print("A strange white mist surrounds you!");
  140.         if (py.flags.free_act)
  141.         msg_print("You are unaffected.");
  142.         else {
  143.         msg_print("You fall asleep.");
  144.         py.flags.paralysis += randint(10) + 4;
  145.         }
  146.     }
  147.     break;
  148.       case 6:               /* Hid Obj */
  149.     (void)delete_object(y, x);
  150.     place_object(y, x);
  151.     msg_print("Hmmm, there was something under this rock.");
  152.     break;
  153.       case 7:               /* STR Dart */
  154.     if (test_hit(125, 0, 0, p_ptr->pac + p_ptr->ptoac, CLA_MISC_HIT)) {
  155.         if (!py.flags.sustain_str) {
  156.         (void)dec_stat(A_STR);
  157.         objdes(tmp, t_ptr, TRUE);
  158.         take_hit(dam, tmp);
  159.         msg_print("A small dart weakens you!");
  160.         } else
  161.         msg_print("A small dart hits you.");
  162.     } else
  163.         msg_print("A small dart barely misses you.");
  164.     break;
  165.       case 8:               /* Teleport */
  166.     teleport_flag = TRUE;
  167.     msg_print("You hit a teleport trap!");
  168.     /* Light up the teleport trap, before we teleport away.  */
  169.     move_light(y, x, y, x);
  170.     break;
  171.       case 9:               /* Rockfall */
  172.     take_hit(dam, "a falling rock");
  173.     (void)delete_object(y, x);
  174.     place_rubble(y, x);
  175.     msg_print("You are hit by falling rock.");
  176.     break;
  177.       case 10:               /* Corrode gas */
  178.     msg_print("A strange red gas surrounds you.");
  179.     corrode_gas("corrosion gas");
  180.     break;
  181.       case 11:               /* Summon mon */
  182.     (void)delete_object(y, x); /* Rune disappears.    */
  183.     num = 2 + randint(3);
  184.     for (i = 0; i < num; i++) {
  185.         ty = y;
  186.         tx = x;
  187.         (void)summon_monster(&ty, &tx, FALSE);
  188.     }
  189.     break;
  190.       case 12:               /* Fire trap */
  191.     msg_print("You are enveloped in flames!");
  192.     fire_dam(dam, "a fire trap");
  193.     break;
  194.       case 13:               /* Acid trap */
  195.     msg_print("You are splashed with acid!");
  196.     acid_dam(dam, "an acid trap");
  197.     break;
  198.       case 14:               /* Poison gas */
  199.     if (!(py.flags.poison_im || py.flags.poison_resist ||
  200.           py.flags.resist_poison))
  201.         poison_gas(dam, "a poison gas trap");
  202.     msg_print("A pungent green gas surrounds you!");
  203.     break;
  204.       case 15:               /* Blind Gas */
  205.     msg_print("A black gas surrounds you!");
  206.     if (!py.flags.blindness_resist)
  207.         py.flags.blind += randint(50) + 50;
  208.     break;
  209.       case 16:               /* Confuse Gas */
  210.     msg_print("A gas of scintillating colors surrounds you!");
  211.     if ((!py.flags.confusion_resist) && (!py.flags.chaos_resist))
  212.         py.flags.confused += randint(15) + 15;
  213.     break;
  214.       case 17:               /* Slow Dart */
  215.     if (test_hit(125, 0, 0, p_ptr->pac + p_ptr->ptoac, CLA_MISC_HIT)) {
  216.         objdes(tmp, t_ptr, TRUE);
  217.         take_hit(dam, tmp);
  218.         msg_print("A small dart hits you!");
  219.         if (py.flags.free_act)
  220.         msg_print("You are unaffected.");
  221.         else
  222.         py.flags.slow += randint(20) + 10;
  223.     } else
  224.         msg_print("A small dart barely misses you.");
  225.     break;
  226.       case 18:               /* CON Dart */
  227.     if (test_hit(125, 0, 0, p_ptr->pac + p_ptr->ptoac, CLA_MISC_HIT)) {
  228.         if (!py.flags.sustain_con) {
  229.         (void)dec_stat(A_CON);
  230.         objdes(tmp, t_ptr, TRUE);
  231.         take_hit(dam, tmp);
  232.         msg_print("A small dart saps your health!");
  233.         } else
  234.         msg_print("A small dart hits you.");
  235.     } else
  236.         msg_print("A small dart barely misses you.");
  237.     break;
  238.       case 19:               /* Secret Door */
  239.     break;
  240.       case 99:               /* Scare Mon */
  241.     break;
  242.  
  243.     /* Town level traps are special,    the stores.     */
  244.       case 101:
  245.       case 102:
  246.       case 103:
  247.       case 104:
  248.       case 105:
  249.       case 106:
  250.       case 107:
  251.       case 108:
  252.     enter_store(t_ptr->subval - 101);
  253.     break;
  254.  
  255.       default:
  256.     msg_print("Unknown trap value.");
  257.     break;
  258.     }
  259. }
  260.  
  261.  
  262. /* Return spell number and failure chance        -RAK-     */
  263. /*
  264.  * returns -1 if no spells in book returns 1 if choose a spell in book to
  265.  * cast returns 0 if don't choose a spell, i.e. exit with an escape 
  266.  */
  267. int 
  268. cast_spell(prompt, item_val, sn, sc)
  269. const char *prompt;
  270. int         item_val;
  271. int        *sn, *sc;
  272. {
  273.     int32u               j1, j2;
  274.     register int         i, k;
  275.     int                  spell[63], result, first_spell;
  276.     register spell_type *s_ptr;
  277.  
  278.     if (!py.misc.pclass)
  279.     return 0;           /* if a warrior, abort as if by ESC -CFT */
  280.     result = (-1);
  281.     i = 0;
  282.     j1 = inventory[item_val].flags;
  283.     j2 = inventory[item_val].flags2;
  284.     first_spell = bit_pos(&j1);
  285. /* set j1 again, since bit_pos modified it */
  286.     j1 = inventory[item_val].flags & spell_learned;
  287.     s_ptr = magic_spell[py.misc.pclass - 1];
  288.     while (j1) {
  289.     k = bit_pos(&j1);
  290.     if (s_ptr[k].slevel <= py.misc.lev) {
  291.         spell[i] = k;
  292.         i++;
  293.     }
  294.     }
  295.     if (!(inventory[item_val].flags & spell_learned))
  296.     first_spell = bit_pos(&j2) + 32;
  297.     j2 = inventory[item_val].flags2 & spell_learned2;
  298.     while (j2) {
  299.     k = bit_pos(&j2);
  300.     if (s_ptr[k + 32].slevel <= py.misc.lev) {
  301.         spell[i] = k + 32;
  302.         i++;
  303.     }
  304.     }
  305.     if (i > 0) {
  306.     result = get_spell(spell, i, sn, sc, prompt, first_spell);
  307.     if (result && magic_spell[py.misc.pclass - 1][*sn].smana > py.misc.cmana) {
  308.         if (class[py.misc.pclass].spell == MAGE)
  309.         result = get_check("You summon your limited strength to cast this one! Confirm?");
  310.         else
  311.         result = get_check("The gods may think you presumptuous for this! Confirm?");
  312.     }
  313.     }
  314.     return (result);
  315. }
  316.  
  317.  
  318. /* Player is on an object.  Many things can happen based -RAK-     */
  319. /* on the TVAL of the object.  Traps are set off, money and most */
  320. /* objects are picked up.  Some objects, such as open doors, just */
  321. /* sit there.                               */
  322. void 
  323. carry(y, x, pickup)
  324. int y, x;
  325. int pickup;
  326. {
  327.     register int         locn, i;
  328.     bigvtype             out_val, tmp_str;
  329.     register cave_type  *c_ptr;
  330.     register inven_type *i_ptr;
  331.  
  332.     c_ptr = &cave[y][x];
  333.     i_ptr = &t_list[c_ptr->tptr];
  334.     i = t_list[c_ptr->tptr].tval;
  335.     if (i <= TV_MAX_PICK_UP) {
  336.     end_find();
  337.     /* There's GOLD in them thar hills!      */
  338.     if (i == TV_GOLD) {
  339.         py.misc.au += i_ptr->cost;
  340.         objdes(tmp_str, i_ptr, TRUE);
  341.         (void)sprintf(out_val,
  342.               "You have found %ld gold pieces worth of %s.",
  343.               (long)i_ptr->cost, tmp_str);
  344.         prt_gold();
  345.         (void)delete_object(y, x);
  346.         msg_print(out_val);
  347.     } else {
  348.         if (pickup && inven_check_num(i_ptr)) { /* Too many objects? */
  349.         if (carry_query_flag) {    /* Okay,  pick it up  */
  350.             objdes(tmp_str, i_ptr, TRUE);
  351.             (void)sprintf(out_val, "Pick up %s? ", tmp_str);
  352.             pickup = get_check(out_val);
  353.         }
  354.         /* Check to see if it will change the players speed. */
  355.         if (pickup && !inven_check_weight(i_ptr)) {
  356.             objdes(tmp_str, i_ptr, TRUE);
  357.             (void)sprintf(out_val,
  358.                   "Exceed your weight limit to pick up %s? ",
  359.                   tmp_str);
  360.             pickup = get_check(out_val);
  361.         }
  362.         /* Attempt to pick up an object.           */
  363.         if (pickup) {
  364.             locn = inven_carry(i_ptr);
  365.             objdes(tmp_str, &inventory[locn], TRUE);
  366.             (void)sprintf(out_val, "You have %s. (%c)", tmp_str, locn + 'a');
  367.             msg_print(out_val);
  368.             (void)delete_object(y, x);
  369.         }
  370.         } else if (pickup) {   /* only if was trying to pick it up...
  371.                     * -CFT */
  372.         objdes(tmp_str, i_ptr, TRUE);
  373.         (void)sprintf(out_val, "You can't carry %s.", tmp_str);
  374.         msg_print(out_val);
  375.         }
  376.     }
  377.     }
  378. /* OOPS!                   */
  379.     else if (i == TV_INVIS_TRAP || i == TV_VIS_TRAP || i == TV_STORE_DOOR)
  380.     hit_trap(y, x);
  381. }
  382.  
  383. void 
  384. check_unique(m_ptr)
  385. monster_type *m_ptr;
  386. {
  387.     if (c_list[m_ptr->mptr].cdefense & UNIQUE)
  388.     u_list[m_ptr->mptr].exist = 0;
  389. }
  390.  
  391.  
  392. void 
  393. delete_unique()
  394. {
  395.     int i;
  396.  
  397.     for (i = 0; i < MAX_CREATURES; i++)
  398.     if (c_list[i].cdefense & UNIQUE)
  399.         u_list[i].exist = 0;
  400. }
  401.  
  402. /* Deletes a monster entry from the level        -RAK-     */
  403. void 
  404. delete_monster(j)
  405.     int j;
  406. {
  407.     register monster_type *m_ptr;
  408.  
  409.     if (j < 2)
  410.     return;               /* trouble? abort! -CFT */
  411.     m_ptr = &m_list[j];
  412.     if (c_list[m_ptr->mptr].cdefense & UNIQUE)
  413.     check_unique(m_ptr);
  414.     cave[m_ptr->fy][m_ptr->fx].cptr = 0;
  415.     if (m_ptr->ml)
  416.     lite_spot((int)m_ptr->fy, (int)m_ptr->fx);
  417.     if (j != mfptr - 1) {
  418. #ifdef TARGET
  419.     /* This targetting code stolen from Morgul -CFT */
  420.     /* Targetted monster dead or compacted.      CDW */
  421.     if (j==target_mon)
  422.         target_mode = FALSE;
  423.  
  424.     /* Targetted monster moved to replace dead or compacted monster   CDW */
  425.     if (target_mon==mfptr-1)
  426.         target_mon = j;
  427. #endif
  428.     m_ptr = &m_list[mfptr - 1];
  429.     cave[m_ptr->fy][m_ptr->fx].cptr = j;
  430.     m_list[j] = m_list[mfptr - 1];
  431.     }
  432.     mfptr--;
  433.     m_list[mfptr] = blank_monster;
  434.     if (mon_tot_mult > 0)
  435.     mon_tot_mult--;
  436. }
  437.  
  438. /*
  439.  * The following two procedures implement the same function as delete
  440.  * monster. However, they are used within creatures(), because deleting a
  441.  * monster while scanning the m_list causes two problems, monsters might get
  442.  * two turns, and m_ptr/monptr might be invalid after the delete_monster.
  443.  * Hence the delete is done in two steps. 
  444.  */
  445. /*
  446.  * fix1_delete_monster does everything delete_monster does except delete the
  447.  * monster record and reduce mfptr, this is called in breathe, and a couple
  448.  * of places in creatures.c 
  449.  */
  450. void 
  451. fix1_delete_monster(j)
  452.     int                 j;
  453. {
  454.     register monster_type *m_ptr;
  455.  
  456.     if (j < 2)
  457.     return;               /* trouble? abort! -CFT */
  458. #ifdef TARGET
  459.     /* Targetted monster dead or compacted.      CDW */
  460.     if (j==target_mon)
  461.     target_mode = FALSE;
  462.  
  463.     /* Targetted monster moved to replace dead or compacted monster   CDW */
  464.     if (target_mon==mfptr-1)
  465.     target_mon = j;
  466. #endif
  467.     m_ptr = &m_list[j];
  468.     if (c_list[m_ptr->mptr].cdefense & UNIQUE)
  469.     check_unique(m_ptr);
  470. /* force the hp negative to ensure that the monster is dead, for example, if
  471.  * the monster was just eaten by another, it will still have positive hit
  472.  * points 
  473.  */
  474.     m_ptr->hp = (-1);
  475.     cave[m_ptr->fy][m_ptr->fx].cptr = 0;
  476.     if (m_ptr->ml)
  477.     lite_spot((int)m_ptr->fy, (int)m_ptr->fx);
  478.     if (mon_tot_mult > 0)
  479.     mon_tot_mult--;
  480. }
  481.  
  482. /* fix2_delete_monster does everything in delete_monster that wasn't done by
  483.  * fix1_monster_delete above, this is only called in creatures() 
  484.  */
  485. void 
  486. fix2_delete_monster(j)
  487. int j;
  488. {
  489.     register monster_type *m_ptr;
  490.  
  491.     if (j < 2)
  492.     return;               /* trouble? abort! -CFT */
  493.     
  494. #ifdef TARGET
  495.     /* Targetted monster dead or compacted. CDW */
  496.     if (j==target_mon)
  497.     target_mode = FALSE;
  498.  
  499.     /* Targetted monster moved to replace dead or compacted monster   CDW */
  500.     if (target_mon==mfptr-1)
  501.     target_mon = j; 
  502. #endif
  503.  
  504.     m_ptr = &m_list[j];           /* Fixed from a c_list ptr to a m_list ptr. -CFT */
  505.     if (c_list[m_ptr->mptr].cdefense & UNIQUE)
  506.     check_unique(m_ptr);
  507.     if (j != mfptr - 1) {
  508.     m_ptr = &m_list[mfptr - 1];
  509.     cave[m_ptr->fy][m_ptr->fx].cptr = j;
  510.     m_list[j] = m_list[mfptr - 1];
  511.     }
  512.     m_list[mfptr - 1] = blank_monster;
  513.     mfptr--;
  514. }
  515.  
  516.  
  517. /* Creates objects nearby the coordinates given        -RAK-      */
  518. static int 
  519. summon_object(y, x, num, typ, good)
  520. int    y, x, num, typ;
  521. int32u good;
  522. {
  523.     register int        i, j, k;
  524.     register cave_type *c_ptr;
  525.     int                 real_typ, res;
  526.  
  527.     if (typ == 1)
  528.     real_typ = 1;           /* typ == 1 -> objects */
  529.     else
  530.     real_typ = 256;           /* typ == 2 -> gold */
  531.     res = 0;
  532.     do {
  533.     i = 0;
  534.     do {
  535.         j = y - 3 + randint(5);
  536.         k = x - 3 + randint(5);
  537.         if (in_bounds(j, k) && los(y, x, j, k)) {
  538.         c_ptr = &cave[j][k];
  539.         if (c_ptr->fval <= MAX_OPEN_SPACE && (c_ptr->tptr == 0)) {
  540.             if (typ == 3) {/* typ == 3 -> 50% objects, 50% gold */
  541.             if (randint(100) < 50)
  542.                 real_typ = 1;
  543.             else
  544.                 real_typ = 256;
  545.             }
  546.             if (real_typ == 1) {
  547.             if (good)
  548.                 place_special(j, k, good);
  549.             else
  550.                 place_object(j, k);
  551.             } else {
  552.             if (good)
  553.                 place_special(j, k, good);
  554.             else
  555.                 place_gold(j, k);
  556.             }
  557.             lite_spot(j, k);
  558.             if (test_light(j, k))
  559.             res += real_typ;
  560.             i = 20;
  561.         }
  562.         }
  563.         i++;
  564.     }
  565.     while (i <= 20);
  566.     num--;
  567.     }
  568.     while (num != 0);
  569.     return res;
  570. }
  571.  
  572.  
  573. /* Deletes object from given location            -RAK-     */
  574. int 
  575. delete_object(y, x)
  576. int y, x;
  577. {
  578.     register int        delete;
  579.     register cave_type *c_ptr;
  580.  
  581.     c_ptr = &cave[y][x];
  582.     if (c_ptr->fval == BLOCKED_FLOOR)
  583.     c_ptr->fval = CORR_FLOOR;
  584.     pusht(c_ptr->tptr);           /* then eliminate it */
  585.     c_ptr->tptr = 0;
  586.     c_ptr->fm = FALSE;
  587.     lite_spot(y, x);
  588.     if (test_light(y, x))
  589.     delete = TRUE;
  590.     else
  591.     delete = FALSE;
  592.     return (delete);
  593. }
  594.  
  595.  
  596. /* Allocates objects upon a creatures death        -RAK-     */
  597. /* Oh well,  another creature bites the dust.  Reward the victor */
  598. /* based on flags set in the main creature record         */
  599. /*
  600.  * Returns a mask of bits from the given flags which indicates what the
  601.  * monster is seen to have dropped.  This may be added to monster memory. 
  602.  */
  603. int32u 
  604. monster_death(y, x, flags, good, win)
  605. int                 y, x;
  606. register int32u     flags;
  607. int32u              good;
  608. int32u              win;
  609. {
  610.     register int i, number;
  611.     int32u       dump, res;
  612.  
  613. #if defined(ATARIST_MWC)
  614.     int32u              holder;       /* avoid a compiler bug */
  615. #endif
  616.  
  617.     if (win) {           /* MORGOTH */
  618.     register int        j, k;
  619.     register cave_type *c_ptr;
  620.     int                 crown = FALSE, grond = FALSE;
  621.  
  622.     i = 0;
  623.     do {
  624.         j = y - 3 + randint(5);
  625.         k = x - 3 + randint(5);
  626.         if (in_bounds(j, k) && los(y, x, j, k)) {
  627.         c_ptr = &cave[j][k];
  628.         if (c_ptr->fval <= MAX_OPEN_SPACE && (c_ptr->tptr == 0)) {
  629.             if (!crown) {
  630.             int                 cur_pos;
  631.             inven_type         *t_ptr;
  632.  
  633.             crown = TRUE;
  634.             cur_pos = popt();
  635.             cave[j][k].tptr = cur_pos;
  636.             invcopy(&t_list[cur_pos], 98);
  637.             t_ptr = &t_list[cur_pos];
  638.             t_ptr->flags |= (TR_STR | TR_DEX | TR_CON | TR_INT | TR_WIS | TR_CHR |
  639.                        TR_SEE_INVIS | TR_CURSED | TR_INFRA);
  640.             t_ptr->flags2 |= (TR_TELEPATHY | TR_LIGHT | TR_ARTIFACT);
  641.             t_ptr->ident |= ID_NOSHOW_TYPE;
  642.             t_ptr->name2 = SN_MORGOTH;
  643.             t_ptr->p1 = 125;
  644.             t_ptr->cost = 10000000L;
  645.             if (cave[j][k].cptr == 1)
  646.                 msg_print("You feel something roll beneath your feet.");
  647.             } else {
  648.             int                 cur_pos;
  649.             inven_type         *t_ptr;
  650.  
  651.             grond = TRUE;
  652.             cur_pos = popt();
  653.             cave[j][k].tptr = cur_pos;
  654.             invcopy(&t_list[cur_pos], 56);
  655.             t_ptr = &t_list[cur_pos];
  656.             t_ptr->name2 = SN_GROND;
  657.             t_ptr->tohit = 5;
  658.             t_ptr->todam = 25;
  659.             t_ptr->damage[0] = 10;
  660.             t_ptr->damage[1] = 8;
  661.             t_ptr->weight = 600;
  662.             t_ptr->flags = (TR_SEE_INVIS | TR_SLAY_EVIL | TR_SLAY_UNDEAD |
  663.                     TR_RES_FIRE | TR_RES_COLD | TR_RES_LIGHT |
  664.                     TR_RES_ACID | TR_SLAY_ANIMAL | TR_SPEED |
  665.                     TR_SLAY_X_DRAGON | TR_AGGRAVATE);
  666.             t_ptr->flags2 = (TR_SLAY_DEMON | TR_SLAY_TROLL | TR_SLAY_ORC |
  667.                     TR_IMPACT | TR_TELEPATHY | TR_ARTIFACT);
  668.             t_ptr->p1 = (-1);
  669.             t_ptr->toac = 10;
  670.             t_ptr->cost = 500000L;
  671.             t_ptr->ident |= ID_SHOW_HITDAM;
  672.             GROND = 1;
  673.             if (cave[j][k].cptr == 1)
  674.                 msg_print("You feel something roll beneath your feet.");
  675.             }
  676.             lite_spot(j, k);
  677.         }
  678.         }
  679.         i++;
  680.     }
  681.     while (!grond && i < 50);
  682.     }
  683. #if !defined(ATARIST_MWC)
  684.     if (flags & CM_CARRY_OBJ)
  685.     i = 1;
  686.     else
  687.     i = 0;
  688.     if (flags & CM_CARRY_GOLD)
  689.     i += 2;
  690.  
  691.     number = 0;
  692.     if ((flags & CM_60_RANDOM) && (randint(100) < 60))
  693.     number++;
  694.     if ((flags & CM_90_RANDOM) && (randint(100) < 90))
  695.     number++;
  696.     if (flags & CM_1D2_OBJ)
  697.     number += randint(2);
  698.     if (flags & CM_2D2_OBJ)
  699.     number += damroll(2, 2);
  700.     if (flags & CM_4D2_OBJ)
  701.     number += damroll(4, 2);
  702.     if (number > 0)
  703.     dump = summon_object(y, x, number, i, good);
  704.     else
  705.     dump = 0;
  706. #else
  707.     holder = CM_CARRY_OBJ;
  708.     if (flags & holder)
  709.     i = 1;
  710.     else
  711.     i = 0;
  712.     holder = CM_CARRY_GOLD;
  713.     if (flags & holder)
  714.     i += 2;
  715.  
  716.     number = 0;
  717.     holder = CM_60_RANDOM;
  718.     if ((flags & holder) && (randint(100) < 60))
  719.     number++;
  720.     holder = CM_90_RANDOM;
  721.     if ((flags & holder) && (randint(100) < 90))
  722.     number++;
  723.     holder = CM_1D2_OBJ;
  724.     if (flags & holder)
  725.     number += randint(2);
  726.     holder = CM_2D2_OBJ;
  727.     if (flags & holder)
  728.     number += damroll(2, 2);
  729.     holder = CM_4D2_OBJ;
  730.     if (flags & holder)
  731.     number += damroll(4, 2);
  732.     if (number > 0)
  733.     dump = summon_object(y, x, number, i, good);
  734.     else
  735.     dump = 0;
  736.  
  737.  
  738. #endif
  739.  
  740. #if defined(ATARIST_MWC)
  741.     holder = CM_WIN;
  742.     if (flags & holder)
  743. #else
  744.     if (flags & CM_WIN)
  745. #endif
  746.     {
  747.     total_winner = TRUE;
  748.     prt_winner();
  749.     msg_print("*** CONGRATULATIONS *** You have won the game.");
  750.     msg_print("You cannot save this game, but you may retire when ready.");
  751.     }
  752.     if (dump) {
  753.     res = 0;
  754.     if (dump & 255)
  755. #ifdef ATARIST_MWC
  756.     {
  757.         holder = CM_CARRY_OBJ;
  758.         res |= holder;
  759.     }
  760. #else
  761.         res |= CM_CARRY_OBJ;
  762. #endif
  763.     if (dump >= 256)
  764. #ifdef ATARIST_MWC
  765.     {
  766.         holder = CM_CARRY_GOLD;
  767.         res |= holder;
  768.     }
  769. #else
  770.         res |= CM_CARRY_GOLD;
  771. #endif
  772.     dump = (dump % 256) + (dump / 256);    /* number of items */
  773.     res |= dump << CM_TR_SHIFT;
  774.     } else
  775.     res = 0;
  776.  
  777.     return res;
  778. }
  779.  
  780. /* return whether a monster is "fearless" and will never run away. -CWS */
  781. static int 
  782. fearless(c_ptr)
  783. creature_type *c_ptr;
  784. {
  785.     int flag = FALSE;
  786.  
  787.     if (c_ptr->cdefense & MINDLESS)
  788.     flag = TRUE;
  789.  
  790.     if (c_ptr->cdefense & UNDEAD) {
  791.     if (c_ptr->spells ||       /* if undead, check to see if it's */
  792.         c_ptr->spells2 ||       /* "mindless", ie has no spells */
  793.         c_ptr->spells3)
  794.         flag = FALSE;       /* found a spell, so not mindless   */
  795.     else
  796.         flag = TRUE;       /* "mindless" undead */
  797.     }
  798.  
  799.     if (c_ptr->cchar == 'E' || c_ptr->cchar == 'g' || c_ptr->cdefense & DEMON)
  800.     flag = TRUE;
  801.  
  802.     if (c_ptr->cdefense & INTELLIGENT)    /* catch intelligent monsters */
  803.     flag = FALSE;
  804.  
  805.     if (!(c_ptr->cmove & CM_MOVE_NORMAL))    /* it can't run away */
  806.     flag = TRUE;
  807.  
  808.     return (flag);
  809. }
  810.  
  811.  
  812. /* Decreases monsters hit points and deletes monster if needed.     */
  813. /* (Picking on my babies.)                   -RAK-   */
  814. /* added fear (DGK) and check whether to print fear messages -CWS */
  815. int 
  816. mon_take_hit(monptr, dam, print_fear)
  817. int monptr, dam, print_fear;
  818. {
  819.     register int32u         i;
  820.     int                     found = FALSE;
  821.     int32                   new_exp, new_exp_frac;
  822.     register monster_type  *m_ptr;
  823.     register struct misc   *p_ptr;
  824.     register creature_type *c_ptr;
  825.     int                     m_take_hit = (-1);
  826.     int32u                  tmp;
  827.     int                     percentage;
  828.     char                    m_name[80];
  829.     vtype                   out_val;
  830.  
  831.     m_ptr = &m_list[monptr];
  832.     m_ptr->hp -= dam;
  833.     m_ptr->csleep = 0;
  834.     c_ptr = &c_list[m_ptr->mptr];
  835.  
  836.     if (m_ptr->hp < 0) {
  837.     if (m_ptr->mptr == (MAX_CREATURES - 1)) {
  838.         char                temp[100];
  839.  
  840.         if (!dun_level) {
  841.         sprintf(temp, "%s/%d", ANGBAND_BONES, c_list[m_ptr->mptr].level);
  842.         } else {
  843.         sprintf(temp, "%s/%d", ANGBAND_BONES, dun_level);
  844.         }
  845.         unlink(temp);
  846.     }
  847.     if (c_list[m_ptr->mptr].cdefense & QUESTOR) {
  848.         for (i = 0; i < DEFINED_QUESTS; i++) {    /* search for monster's
  849.                              * lv, not... */
  850.         if (quests[i] == c_list[m_ptr->mptr].level) {    /* ...cur lv. -CFT */
  851.             quests[i] = 0;
  852.             found = TRUE;
  853.             break;
  854.         }
  855.         }
  856.         if (found) {
  857.         if ((unsigned) dun_level != c_list[m_ptr->mptr].level) {
  858.             /* just mesg */
  859.             msg_print("Well done!!  Now continue onward towards Morgoth.");
  860.         } else {       /* stairs and mesg */
  861.             cave_type          *ca_ptr;
  862.             int                 cur_pos;
  863.  
  864.             ca_ptr = &cave[m_ptr->fy][m_ptr->fx];
  865.             if (ca_ptr->tptr != 0) {    /* don't overwrite artifact -CFT */
  866.             int                 ty = m_ptr->fy, tx = m_ptr->fx, ny, nx;
  867.  
  868.             while ((cave[ty][tx].tptr != 0) &&
  869.               (t_list[cave[ty][tx].tptr].tval >= TV_MIN_WEAR) &&
  870.               (t_list[cave[ty][tx].tptr].tval <= TV_MAX_WEAR) &&
  871.              (t_list[cave[ty][tx].tptr].flags2 & TR_ARTIFACT)) {
  872.                 do { /* pick new possible spot */
  873.                 ny = ty + (int8u) randint(3) - 2;
  874.                 nx = tx + (int8u) randint(3) - 2;
  875.                 } while (!in_bounds(ny, nx) ||
  876.                      (cave[ny][nx].fval > MAX_OPEN_SPACE));
  877.                 ty = ny;    /* this is a new spot, not in a wall/door/etc */
  878.                 tx = nx;
  879.             } /* ok, to exit this, [ty][tx] must not be artifact
  880.                * -CFT */
  881.             if (cave[ty][tx].tptr != 0)    /* so we can delete it -CFT */
  882.                 (void)delete_object(ty, tx);
  883.             ca_ptr = &cave[ty][tx];    /* put stairway here... */
  884.             }
  885.             cur_pos = popt();
  886.             ca_ptr->tptr = cur_pos;
  887.             invcopy(&t_list[cur_pos], OBJ_DOWN_STAIR);
  888.             msg_print("Well done!! Go for it!");
  889.             msg_print("A magical stairway appears...");
  890.         } /* if-else for stairway */
  891.         } /* if found */
  892.     } /* if quest monster */
  893.     object_level = (dun_level + c_ptr->level) >> 1;
  894.     coin_type = 0;
  895.     get_coin_type(c_ptr);
  896.     i = monster_death((int)m_ptr->fy, (int)m_ptr->fx,
  897.               c_list[m_ptr->mptr].cmove,
  898.               (c_list[m_ptr->mptr].cdefense & (SPECIAL | GOOD)),
  899.               (c_list[m_ptr->mptr].cmove & WINNER));
  900.     coin_type = 0;
  901.     if ((py.flags.blind < 1 && m_ptr->ml) ||
  902.         (c_list[m_ptr->mptr].cmove & CM_WIN) ||
  903.         (c_list[m_ptr->mptr].cdefense & UNIQUE)) {
  904.         /* recall even invisible uniques */
  905.  
  906.         tmp = (c_recall[m_ptr->mptr].r_cmove & CM_TREASURE) >> CM_TR_SHIFT;
  907.         if (tmp > ((i & CM_TREASURE) >> CM_TR_SHIFT))
  908.         i = (i & ~CM_TREASURE) | (tmp << CM_TR_SHIFT);
  909.         c_recall[m_ptr->mptr].r_cmove =
  910.         (c_recall[m_ptr->mptr].r_cmove & ~CM_TREASURE) | i;
  911.         if (c_recall[m_ptr->mptr].r_kills < MAX_SHORT)
  912.         c_recall[m_ptr->mptr].r_kills++;
  913.     }
  914.     c_ptr = &c_list[m_ptr->mptr];
  915.     p_ptr = &py.misc;
  916.  
  917.     if (c_ptr->cdefense & UNIQUE) {
  918.         u_list[m_ptr->mptr].exist = 0;
  919.         u_list[m_ptr->mptr].dead = 1;
  920.     }
  921.     new_exp = ((long)c_ptr->mexp * c_ptr->level) / p_ptr->lev;
  922.     new_exp_frac = ((((long)c_ptr->mexp * c_ptr->level) % p_ptr->lev)
  923.             * 0x10000L / p_ptr->lev) + p_ptr->exp_frac;
  924.     if (new_exp_frac >= 0x10000L) {
  925.         new_exp++;
  926.         p_ptr->exp_frac = new_exp_frac - 0x10000L;
  927.     } else
  928.         p_ptr->exp_frac = new_exp_frac;
  929.  
  930.     p_ptr->exp += new_exp;
  931.     if (p_ptr->exp < p_ptr->max_exp) /* If player is drained, let him get
  932.                                           * something: 10% is better than nothing -CFT */
  933.         p_ptr->max_exp += new_exp/10;
  934.  
  935.     /* can't call prt_experience() here, as that would result in "new level"
  936.      * message appearing before "monster dies" message 
  937.      */
  938.     m_take_hit = m_ptr->mptr;
  939.     /* in case this is called from within creatures(), this is a horrible
  940.      * hack, the m_list/creatures() code needs to be rewritten 
  941.      */
  942.     if (hack_monptr < monptr)
  943.         delete_monster(monptr);
  944.     else
  945.         fix1_delete_monster(monptr);
  946.     monster_is_afraid = 0;
  947.     } else {
  948.     if (m_ptr->maxhp <= 0)       /* Then fix it! -DGK */
  949.         m_ptr->maxhp = 1;
  950.     percentage = (m_ptr->hp * 100L) / (m_ptr->maxhp);
  951.  
  952.     if (fearless(c_ptr)) {
  953.         monster_is_afraid = 0;
  954.         return (-1);
  955.     }
  956.     if (!(m_ptr->monfear) &&
  957.         ((percentage <= 10 && randint(10) <= percentage) || (dam >= m_ptr->hp)))
  958.     /*
  959.      * Run if at 10% or less of max hit points, or got hit for half its
  960.      * current hit points -DGK 
  961.      */
  962.     {
  963.         monster_is_afraid = 1;
  964.         if (print_fear && m_ptr->ml &&
  965.         los(char_row, char_col, m_ptr->fy, m_ptr->fx)) {
  966.         monster_name(m_name, m_ptr, c_ptr);
  967.         sprintf(out_val, "%s flees in terror!", m_name);
  968.         msg_print(out_val);
  969.         }
  970.         m_ptr->monfear = randint(10) + ((dam >= m_ptr->hp && percentage > 7) ?
  971.                         20 : (11 - percentage) * 5);
  972.     } else if (m_ptr->monfear) {
  973.         m_ptr->monfear -= randint(dam);
  974.         if (m_ptr->monfear <= 0) {
  975.         if (monster_is_afraid == 1)
  976.             monster_is_afraid = (-1);
  977.         m_ptr->monfear = 0;
  978.         if (m_ptr->ml && print_fear) {
  979.             char                sex = c_ptr->gender;
  980.  
  981.             monster_name(m_name, m_ptr, c_ptr);
  982.             sprintf(out_val, "%s recovers %s courage.", m_name,
  983.                 (sex == 'm' ? "his" : sex == 'f' ? "her" :
  984.                  sex == 'p' ? "their" : "its"));
  985.             msg_print(out_val);
  986.         }
  987.         }
  988.     }
  989.     m_take_hit = (-1);
  990.     }
  991.     return (m_take_hit);
  992. }
  993.  
  994.  
  995. /* Player attacks a (poor, defenseless) creature    -RAK-     */
  996. static void 
  997. py_attack(y, x)
  998. int y, x;
  999. {
  1000.     register int        k, blows;
  1001.     int                 crptr, monptr, tot_tohit, base_tohit;
  1002.     vtype               m_name, out_val;
  1003.     register inven_type    *i_ptr;
  1004.     register struct misc   *p_ptr;
  1005.  
  1006.     crptr = cave[y][x].cptr;
  1007.     monptr = m_list[crptr].mptr;
  1008.  
  1009.     m_list[crptr].csleep = 0;
  1010.     i_ptr = &inventory[INVEN_WIELD];
  1011. /* Does the player know what he's fighting?       */
  1012.     if (!m_list[crptr].ml)
  1013.     (void)strcpy(m_name, "it");
  1014.     else {
  1015.     if (c_list[monptr].cdefense & UNIQUE)
  1016.         (void)sprintf(m_name, "%s", c_list[monptr].name);
  1017.     else
  1018.         (void)sprintf(m_name, "the %s", c_list[monptr].name);
  1019.     }
  1020.  
  1021.     if (i_ptr->tval != TV_NOTHING) /* Proper weapon */
  1022.     blows = attack_blows((int)i_ptr->weight, &tot_tohit);
  1023.     else {               /* Bare hands?   */
  1024.     blows = 2;
  1025.     tot_tohit = (-3);
  1026.     }
  1027.     if ((i_ptr->tval >= TV_SLING_AMMO) && (i_ptr->tval <= TV_ARROW))
  1028.     /* Fix for arrows */
  1029.     blows = 1;
  1030.     p_ptr = &py.misc;
  1031.     tot_tohit += p_ptr->ptohit;
  1032. /* if creature not lit, make it more difficult to hit */
  1033.     if (m_list[crptr].ml)
  1034.     base_tohit = p_ptr->bth;
  1035.     else
  1036.     base_tohit = (p_ptr->bth / 2) - (tot_tohit * (BTH_PLUS_ADJ - 1))
  1037.         - (p_ptr->lev * class_level_adj[p_ptr->pclass][CLA_BTH] / 2);
  1038.  
  1039. /* Loop for number of blows,    trying to hit the critter.      */
  1040.     monster_is_afraid = 0;       /* redo fear messages -CWS        */
  1041.     do {
  1042.     if (test_hit(base_tohit, (int)p_ptr->lev, tot_tohit,
  1043.              (int)c_list[monptr].ac, CLA_BTH)) {
  1044.  
  1045.         if (!wizard) {
  1046.         (void) sprintf(out_val, "You hit %s.", m_name);
  1047.         msg_print(out_val);
  1048.         }
  1049.  
  1050.         if (i_ptr->tval != TV_NOTHING) {
  1051.         k = pdamroll(i_ptr->damage);
  1052.         k = tot_dam(i_ptr, k, monptr);
  1053.         k = critical_blow((int)i_ptr->weight, tot_tohit, k, CLA_BTH);
  1054.         } else {           /* Bare hands!?  */
  1055.         k = damroll(1, 1);
  1056.         k = critical_blow(1, 0, k, CLA_BTH);
  1057.         }
  1058.         k += p_ptr->ptodam;
  1059.  
  1060.         if (wizard) {
  1061.         (void)sprintf(out_val,
  1062.                   "You hit %s with %d hp, doing %d+%d damage.",
  1063.                   m_name, m_list[crptr].hp, (k - p_ptr->ptodam),
  1064.                   p_ptr->ptodam);
  1065.         msg_print(out_val);
  1066.         }
  1067.  
  1068.         if (k < 0)
  1069.         k = 0;
  1070.  
  1071.         if (py.flags.confuse_monster) {
  1072.         py.flags.confuse_monster = FALSE;
  1073.         msg_print("Your hands stop glowing.");
  1074.         if ((c_list[monptr].cdefense & CHARM_SLEEP)
  1075.             || (randint(MAX_MONS_LEVEL) < c_list[monptr].level))
  1076.             (void)sprintf(out_val, "%s is unaffected.", m_name);
  1077.         else {
  1078.             (void)sprintf(out_val, "%s appears confused.", m_name);
  1079.             m_list[crptr].confused = TRUE;
  1080.         }
  1081.         if ((out_val[0] >= 'a') && (out_val[0] <= 'z'))
  1082.             out_val[0] -= 32;    /* upcase, because starts sentence
  1083.                      * -CFT */
  1084.         msg_print(out_val);
  1085.         if (m_list[crptr].ml && randint(4) == 1)
  1086.             c_recall[monptr].r_cdefense |=
  1087.             c_list[monptr].cdefense & CHARM_SLEEP;
  1088.         }
  1089.         if (k < 0)
  1090.         k = 0;           /* no neg damage! */
  1091.  
  1092.     /* See if we done it in.                 */
  1093.         if (mon_take_hit(crptr, k, FALSE) >= 0) {    /* never print msgs -CWS */
  1094.         if ((c_list[monptr].cdefense & (DEMON|UNDEAD|MINDLESS)) ||
  1095.             (c_list[monptr].cchar == 'E') ||
  1096.             (c_list[monptr].cchar == 'v') ||
  1097.             (c_list[monptr].cchar == 'g'))
  1098.             (void)sprintf(out_val, "You have destroyed %s.", m_name);
  1099.         else
  1100.             (void)sprintf(out_val, "You have slain %s.", m_name);
  1101.         msg_print(out_val);
  1102.         prt_experience();
  1103.         blows = 0;
  1104.         }
  1105.         if ((i_ptr->tval >= TV_SLING_AMMO)
  1106.         && (i_ptr->tval <= TV_ARROW)) {    /* Use missiles up */
  1107.         i_ptr->number--;
  1108.         inven_weight -= i_ptr->weight;
  1109.         py.flags.status |= PY_STR_WGT;
  1110.         if (i_ptr->number == 0) {
  1111.             equip_ctr--;
  1112.             py_bonuses(i_ptr, -1);
  1113.             invcopy(i_ptr, OBJ_NOTHING);
  1114.             calc_bonuses();
  1115.         }
  1116.         }
  1117.     } else {
  1118.         (void)sprintf(out_val, "You miss %s.", m_name);
  1119.         msg_print(out_val);
  1120.     }
  1121.     blows--;
  1122.     }
  1123.     while (blows >= 1);
  1124.  
  1125. /* redo fear messages to only print at the end -CWS */
  1126.  
  1127.     if (!m_list[crptr].ml)
  1128.     (void)strcpy(m_name, "It");
  1129.     else {
  1130.     if (c_list[monptr].cdefense & UNIQUE)
  1131.         (void)sprintf(m_name, "%s", c_list[monptr].name);
  1132.     else
  1133.         (void)sprintf(m_name, "The %s", c_list[monptr].name);
  1134.     }
  1135.  
  1136.     if (monster_is_afraid == 1) {
  1137.     sprintf(out_val, "%s flees in terror!", m_name);
  1138.     msg_print(out_val);
  1139.     }
  1140.     if (monster_is_afraid == -1) {
  1141.     char                sex = c_list[monptr].gender;
  1142.  
  1143.     sprintf(out_val, "%s recovers %s courage.", m_name,
  1144.         (sex == 'm' ? "his" : sex == 'f' ? "her" :
  1145.          sex == 'p' ? "their" : "its"));
  1146.     msg_print(out_val);
  1147.     }
  1148. }
  1149.  
  1150.  
  1151. /* Moves player from one space to another.        -RAK-     */
  1152. /* Note: This routine has been pre-declared; see that for argument */
  1153. void 
  1154. move_char(dir, do_pickup)
  1155. int dir, do_pickup;
  1156. {
  1157.     int                 old_row, old_col, old_find_flag;
  1158.     int                 y, x;
  1159.     register int        i, j;
  1160.     register cave_type *c_ptr, *d_ptr;
  1161.  
  1162.     if (((py.flags.confused > 0) || (py.flags.stun > 0)) &&    /* Confused/Stunned?  */
  1163.     (randint(4) > 1) &&       /* 75% random movement */
  1164.     (dir != 5)) {           /* Never random if sitting */
  1165.     dir = randint(9);
  1166.     end_find();
  1167.     }
  1168.     y = char_row;
  1169.     x = char_col;
  1170.     if (mmove(dir, &y, &x)) {       /* Legal move?          */
  1171.     c_ptr = &cave[y][x];
  1172.     /* if there is no creature, or an unlit creature in the walls then... */
  1173.     /* disallow attacks against unlit creatures in walls because moving into
  1174.      * a wall is a free turn normally, hence don't give player free turns
  1175.      * attacking each wall in an attempt to locate the invisible creature,
  1176.      * instead force player to tunnel into walls which always takes a turn 
  1177.      */
  1178.     if ((c_ptr->cptr < 2)
  1179.       || (!m_list[c_ptr->cptr].ml && c_ptr->fval >= MIN_CLOSED_SPACE)) {
  1180.         if (c_ptr->fval <= MAX_OPEN_SPACE) {    /* Open floor spot     */
  1181.         /* Make final assignments of char co-ords */
  1182.         old_row = char_row;
  1183.         old_col = char_col;
  1184.         char_row = y;
  1185.         char_col = x;
  1186.         /* Move character record (-1)           */
  1187.         move_rec(old_row, old_col, char_row, char_col);
  1188.         /* Check for new panel               */
  1189.         if (get_panel(char_row, char_col, FALSE))
  1190.             prt_map();
  1191.         /* Check to see if he should stop           */
  1192.         if (find_flag)
  1193.             area_affect(dir, char_row, char_col);
  1194.         /* Check to see if he notices something  */
  1195.         /* fos may be negative if have good rings of searching */
  1196.         if ((py.misc.fos <= 1) || (randint(py.misc.fos) == 1) ||
  1197.             (py.flags.status & PY_SEARCH))
  1198.             search(char_row, char_col, py.misc.srh);
  1199.         /* A room of light should be lit.         */
  1200.         if ((c_ptr->fval == LIGHT_FLOOR) ||
  1201.             (c_ptr->fval == NT_LIGHT_FLOOR)) {
  1202.             if (!c_ptr->pl && !py.flags.blind)
  1203.             light_room(char_row, char_col);
  1204.         }
  1205.         /* In doorway of light-room?           */
  1206.         else if (c_ptr->lr && (py.flags.blind < 1)) {
  1207.             int8u lit = FALSE;    /* only call light_room once... -CFT */
  1208.  
  1209.             for (i = (char_row - 1); !lit && i <= (char_row + 1); i++)
  1210.             for (j = (char_col - 1); !lit && j <= (char_col + 1); j++) {
  1211.                 d_ptr = &cave[i][j];
  1212.                 if (((d_ptr->fval == LIGHT_FLOOR) ||
  1213.                  (d_ptr->fval == NT_LIGHT_FLOOR)) &&
  1214.                 (!d_ptr->pl)) {
  1215.                 /* move light 1st, or corridor may be perm lit */
  1216.                 move_light(old_row, old_col, char_row, char_col);
  1217.                 light_room(char_row, char_col);
  1218.                 lit = TRUE;    /* okay, we can stop now... -CFT */
  1219.                 }
  1220.             }
  1221.         }
  1222.         /* Move the light source               */
  1223.         move_light(old_row, old_col, char_row, char_col);
  1224.         /* An object is beneath him.         */
  1225.         if (c_ptr->tptr != 0) {
  1226.             i = t_list[c_ptr->tptr].tval;
  1227.             if (i == TV_INVIS_TRAP || i == TV_VIS_TRAP
  1228.             || i == TV_STORE_DOOR || !prompt_carry_flag
  1229.             || i == TV_GOLD)
  1230.             carry(char_row, char_col, do_pickup);
  1231.             else if (prompt_carry_flag && i != TV_OPEN_DOOR
  1232.                  && i != TV_UP_STAIR && i != TV_DOWN_STAIR) {
  1233.             inven_type         *i_ptr;
  1234.             bigvtype            tmp_str, tmp2_str;
  1235.  
  1236.             i_ptr = &t_list[cave[char_row][char_col].tptr];
  1237.             objdes(tmp_str, i_ptr, TRUE);
  1238.             sprintf(tmp2_str, "You see %s.", tmp_str);
  1239.             msg_print(tmp2_str);
  1240.             }
  1241.         /* if stepped on falling rock trap, and space contains
  1242.          * rubble, then step back into a clear area 
  1243.          */
  1244.             if (t_list[c_ptr->tptr].tval == TV_RUBBLE) {
  1245.             move_rec(char_row, char_col, old_row, old_col);
  1246.             move_light(char_row, char_col, old_row, old_col);
  1247.             char_row = old_row;
  1248.             char_col = old_col;
  1249.     /* check to see if we have stepped back onto another trap, if so, set it off */
  1250.             c_ptr = &cave[char_row][char_col];
  1251.             if (c_ptr->tptr != 0) {
  1252.                 i = t_list[c_ptr->tptr].tval;
  1253.                 if (i == TV_INVIS_TRAP || i == TV_VIS_TRAP
  1254.                 || i == TV_STORE_DOOR)
  1255.                 hit_trap(char_row, char_col);
  1256.             }
  1257.             }
  1258.         }
  1259.         } else {           /* Can't move onto floor space */
  1260.         if (!find_flag && (c_ptr->tptr != 0)) {
  1261.             if (t_list[c_ptr->tptr].tval == TV_RUBBLE)
  1262.             msg_print("There is rubble blocking your way.");
  1263.             else if (t_list[c_ptr->tptr].tval == TV_CLOSED_DOOR)
  1264.             msg_print("There is a closed door blocking your way.");
  1265.         } else
  1266.             end_find();
  1267.         free_turn_flag = TRUE;
  1268.         }
  1269.     } else {           /* Attacking a creature! */
  1270.         old_find_flag = find_flag;
  1271.         end_find();
  1272.     /* if player can see monster, and was in find mode, then nothing */
  1273.         if (m_list[c_ptr->cptr].ml && old_find_flag) {
  1274.         /* did not do anything this turn */
  1275.         free_turn_flag = TRUE;
  1276.         } else {
  1277.         if (py.flags.afraid < 1)    /* Coward?     */
  1278.             py_attack(y, x);
  1279.         else           /* Coward!     */
  1280.             msg_print("You are too afraid!");
  1281.         }
  1282.     }
  1283.     }
  1284. }
  1285.  
  1286.  
  1287. /* Chests have traps too.                -RAK-     */
  1288. /* Note: Chest traps are based on the FLAGS value         */
  1289. static void 
  1290. chest_trap(y, x)
  1291. int y, x;
  1292. {
  1293.     register int        i;
  1294.     int                 j, k;
  1295.     register inven_type *t_ptr;
  1296.  
  1297.     t_ptr = &t_list[cave[y][x].tptr];
  1298.     if (CH_LOSE_STR & t_ptr->flags) {
  1299.     msg_print("A small needle has pricked you!");
  1300.     if (!py.flags.sustain_str) {
  1301.         (void)dec_stat(A_STR);
  1302.         take_hit(damroll(1, 4), "a poison needle");
  1303.         msg_print("You feel weakened!");
  1304.     } else
  1305.         msg_print("You are unaffected.");
  1306.     }
  1307.     if (CH_POISON & t_ptr->flags) {
  1308.     msg_print("A small needle has pricked you!");
  1309.     take_hit(damroll(1, 6), "a poison needle");
  1310.     if (!(py.flags.poison_resist || py.flags.resist_poison ||
  1311.           py.flags.poison_im))
  1312.         py.flags.poisoned += 10 + randint(20);
  1313.     }
  1314.     if (CH_PARALYSED & t_ptr->flags) {
  1315.     msg_print("A puff of yellow gas surrounds you!");
  1316.     if (py.flags.free_act)
  1317.         msg_print("You are unaffected.");
  1318.     else {
  1319.         msg_print("You choke and pass out.");
  1320.         py.flags.paralysis = 10 + randint(20);
  1321.     }
  1322.     }
  1323.     if (CH_SUMMON & t_ptr->flags) {
  1324.     for (i = 0; i < 3; i++) {
  1325.         j = y;
  1326.         k = x;
  1327.         (void)summon_monster(&j, &k, FALSE);
  1328.     }
  1329.     }
  1330.     if (CH_EXPLODE & t_ptr->flags) {
  1331.     msg_print("There is a sudden explosion!");
  1332.     (void)delete_object(y, x);
  1333.     take_hit(damroll(5, 8), "an exploding chest");
  1334.     }
  1335. }
  1336.  
  1337.  
  1338. /* Opens a closed door or closed chest.        -RAK-     */
  1339. void 
  1340. openobject()
  1341. {
  1342.     int                    y, x, i, dir;
  1343.     int                    flag, no_object;
  1344.     register cave_type    *c_ptr;
  1345.     register inven_type   *t_ptr;
  1346.     register struct misc  *p_ptr;
  1347.     register monster_type *m_ptr;
  1348.     vtype                  m_name, out_val;
  1349. #ifdef TARGET
  1350.     int temp = target_mode; /* targetting will screw up get_dir, so we save
  1351.                    target_mode, then turn it off -CFT */
  1352. #endif
  1353.  
  1354.     y = char_row;
  1355.     x = char_col;
  1356. #ifdef TARGET
  1357.     target_mode = FALSE;
  1358. #endif
  1359.     if (get_dir(NULL, &dir)) {
  1360.     (void)mmove(dir, &y, &x);
  1361.     c_ptr = &cave[y][x];
  1362.     no_object = FALSE;
  1363.     if (c_ptr->cptr > 1 && c_ptr->tptr != 0 &&
  1364.         (t_list[c_ptr->tptr].tval == TV_CLOSED_DOOR
  1365.          || t_list[c_ptr->tptr].tval == TV_CHEST)) {
  1366.         m_ptr = &m_list[c_ptr->cptr];
  1367.         if (m_ptr->ml) {
  1368.         if (c_list[m_ptr->mptr].cdefense & UNIQUE)
  1369.             (void)sprintf(m_name, "%s", c_list[m_ptr->mptr].name);
  1370.         else
  1371.             (void)sprintf(m_name, "The %s", c_list[m_ptr->mptr].name);
  1372.         } else
  1373.         (void)strcpy(m_name, "Something");
  1374.         (void)sprintf(out_val, "%s is in your way!", m_name);
  1375.         msg_print(out_val);
  1376.     } else if (c_ptr->tptr != 0)
  1377.     /* Closed door         */
  1378.         if (t_list[c_ptr->tptr].tval == TV_CLOSED_DOOR) {
  1379.         t_ptr = &t_list[c_ptr->tptr];
  1380.         if (t_ptr->p1 > 0) {
  1381.             p_ptr = &py.misc;
  1382.             i = p_ptr->disarm + 2 * todis_adj() + stat_adj(A_INT)
  1383.             + (class_level_adj[p_ptr->pclass][CLA_DISARM]
  1384.                * p_ptr->lev / 3);
  1385.     /* give a 1/50 chance of opening anything, anyway -CWS */
  1386.             if ((i - t_ptr->p1) < 2)
  1387.             i = t_ptr->p1 + 2;
  1388.             if (py.flags.confused > 0)
  1389.             msg_print("You are too confused to pick the lock.");
  1390.             else if ((i - t_ptr->p1) > randint(100)) {
  1391.             msg_print("You have picked the lock.");
  1392.             py.misc.exp++;
  1393.             prt_experience();
  1394.             t_ptr->p1 = 0;
  1395.             } else
  1396.             count_msg_print("You failed to pick the lock.");
  1397.         } else if (t_ptr->p1 < 0)    /* It's stuck      */
  1398.             msg_print("It appears to be stuck.");
  1399.         if (t_ptr->p1 == 0) {
  1400.             invcopy(&t_list[c_ptr->tptr], OBJ_OPEN_DOOR);
  1401.             c_ptr->fval = CORR_FLOOR;
  1402.             lite_spot(y, x);
  1403.             check_view();
  1404.             command_count = 0;
  1405.         }
  1406.         }
  1407.     /* Open a closed chest.             */
  1408.         else if (t_list[c_ptr->tptr].tval == TV_CHEST) {
  1409.         p_ptr = &py.misc;
  1410.         i = p_ptr->disarm + 2 * todis_adj() + stat_adj(A_INT)
  1411.             + (class_level_adj[p_ptr->pclass][CLA_DISARM] * p_ptr->lev / 3);
  1412.         t_ptr = &t_list[c_ptr->tptr];
  1413.         flag = FALSE;
  1414.         if (CH_LOCKED & t_ptr->flags)
  1415.             if (py.flags.confused > 0)
  1416.             msg_print("You are too confused to pick the lock.");
  1417.             else if ((i - (int)t_ptr->level) > randint(100)) {
  1418.             msg_print("You have picked the lock.");
  1419.             flag = TRUE;
  1420.             py.misc.exp += t_ptr->level;
  1421.             prt_experience();
  1422.             } else
  1423.             count_msg_print("You failed to pick the lock.");
  1424.         else
  1425.             flag = TRUE;
  1426.         if (flag) {
  1427.             t_ptr->flags &= ~CH_LOCKED;
  1428.             t_ptr->name2 = SN_EMPTY;
  1429.             known2(t_ptr);
  1430.             t_ptr->cost = 0;
  1431.         }
  1432.         flag = FALSE;
  1433.         /* Was chest still trapped?     (Snicker)   */
  1434.         if ((CH_LOCKED & t_ptr->flags) == 0) {
  1435.             chest_trap(y, x);
  1436.             if (c_ptr->tptr != 0)
  1437.             flag = TRUE;
  1438.         }
  1439.         /* Chest treasure is allocated as if a creature   */
  1440.         /* had been killed.                   */
  1441.         if (flag) {
  1442.         /*
  1443.          * clear the cursed chest/monster win flag, so that people
  1444.          * can not win by opening a cursed chest 
  1445.          */
  1446.             t_ptr->flags &= ~TR_CURSED;
  1447.  
  1448.         /* generate based on level chest was found on - dbd */
  1449.             object_level = t_ptr->p1;
  1450.  
  1451.             /* but let's not get too crazy with storebought chests -CWS */
  1452.             if (t_ptr->ident & ID_STOREBOUGHT) {
  1453.             if (object_level > 20)
  1454.                 object_level = 20;
  1455.             }
  1456.  
  1457.             if (object_level < 0) /* perform some sanity checking -CWS */
  1458.             object_level = 0;
  1459.             if (object_level > MAX_OBJ_LEVEL)
  1460.             object_level = MAX_OBJ_LEVEL;
  1461.  
  1462.             coin_type = 0;
  1463.             opening_chest = TRUE; /* don't generate another chest -CWS */
  1464.             (void)monster_death(y, x, t_list[c_ptr->tptr].flags, 0, 0);
  1465.             t_list[c_ptr->tptr].flags = 0;
  1466.             opening_chest = FALSE;
  1467.         }
  1468.         } else
  1469.         no_object = TRUE;
  1470.     else
  1471.         no_object = TRUE;
  1472.  
  1473.     if (no_object) {
  1474.         msg_print("I do not see anything you can open there.");
  1475.         free_turn_flag = TRUE;
  1476.     }
  1477.     }
  1478. #ifdef TARGET
  1479.     target_mode = temp;
  1480. #endif
  1481. }
  1482.  
  1483.  
  1484. /* Closes an open door.                -RAK-     */
  1485. void 
  1486. closeobject()
  1487. {
  1488.     int                    y, x, dir, no_object;
  1489.     vtype                  out_val, m_name;
  1490.     register cave_type    *c_ptr;
  1491.     register monster_type *m_ptr;
  1492. #ifdef TARGET
  1493.     int temp = target_mode; /* targetting will screw up get_dir, so we save
  1494.                    target_mode, then turn it off -CFT */
  1495. #endif
  1496.  
  1497.     y = char_row;
  1498.     x = char_col;
  1499. #ifdef TARGET
  1500.     target_mode = FALSE;
  1501. #endif
  1502.     if (get_dir(NULL, &dir)) {
  1503.     (void)mmove(dir, &y, &x);
  1504.     c_ptr = &cave[y][x];
  1505.     no_object = FALSE;
  1506.     if (c_ptr->tptr != 0)
  1507.         if (t_list[c_ptr->tptr].tval == TV_OPEN_DOOR)
  1508.         if (c_ptr->cptr == 0)
  1509.             if (t_list[c_ptr->tptr].p1 == 0) {
  1510.             invcopy(&t_list[c_ptr->tptr], OBJ_CLOSED_DOOR);
  1511.             c_ptr->fval = BLOCKED_FLOOR;
  1512.             lite_spot(y, x);
  1513.             } else
  1514.             msg_print("The door appears to be broken.");
  1515.         else {
  1516.             m_ptr = &m_list[c_ptr->cptr];
  1517.             if (m_ptr->ml) {
  1518.             if (c_list[m_ptr->mptr].cdefense & UNIQUE)
  1519.                 (void)sprintf(m_name, "%s", c_list[m_ptr->mptr].name);
  1520.             else
  1521.                 (void)sprintf(m_name, "The %s", c_list[m_ptr->mptr].name);
  1522.             } else
  1523.             (void)strcpy(m_name, "Something");
  1524.             (void)sprintf(out_val, "%s is in your way!", m_name);
  1525.             msg_print(out_val);
  1526.         }
  1527.         else
  1528.         no_object = TRUE;
  1529.     else
  1530.         no_object = TRUE;
  1531.  
  1532.     if (no_object) {
  1533.         msg_print("I do not see anything you can close there.");
  1534.         free_turn_flag = TRUE;
  1535.     }
  1536.     }
  1537. #ifdef TARGET
  1538.     target_mode = temp;
  1539. #endif
  1540. }
  1541.  
  1542.  
  1543. /* Tunneling through real wall: 10, 11, 12        -RAK-     */
  1544. /* Used by TUNNEL and WALL_TO_MUD                 */
  1545. int 
  1546. twall(y, x, t1, t2)
  1547. int y, x, t1, t2;
  1548. {
  1549.     register int        i, j;
  1550.     register cave_type *c_ptr;
  1551.     int                 res, found;
  1552.  
  1553.     res = FALSE;
  1554.     if (t1 > t2) {
  1555.     c_ptr = &cave[y][x];
  1556.     if (c_ptr->tptr) { /* secret door or rubble or gold -CFT */
  1557.         if (t_list[c_ptr->tptr].tval == TV_RUBBLE) {
  1558.         delete_object(y,x); /* blow it away... */
  1559.         if (randint(10)==1){
  1560.             place_object(y,x); /* and drop a goodie! */
  1561.         }
  1562.         }
  1563.         else if (t_list[c_ptr->tptr].tval >= TV_MIN_DOORS)
  1564.         delete_object(y,x); /* no more door... */
  1565.     } /* if object there.... */
  1566.     
  1567.     c_ptr->fm = FALSE;
  1568.     if (panel_contains(y, x))
  1569.         if ((c_ptr->tl || c_ptr->pl) && c_ptr->tptr != 0) {
  1570.         msg_print("You have found something!");
  1571.         c_ptr->fm = TRUE;
  1572.         }        
  1573.     
  1574. /* should become a room space, check to see whether it should be
  1575.  * LIGHT_FLOOR or DARK_FLOOR
  1576.  */
  1577.     if (c_ptr->lr) {
  1578.         found = FALSE;
  1579.         for (i = y - 1; i <= y + 1; i++)
  1580.         for (j = x - 1; j <= x + 1; j++)
  1581.             if (cave[i][j].fval <= MAX_CAVE_ROOM) {
  1582.             c_ptr->fval = cave[i][j].fval;
  1583.             c_ptr->pl = cave[i][j].pl;
  1584.             found = TRUE;
  1585.             break;
  1586.             }
  1587.         if (!found) {
  1588.         c_ptr->fval = CORR_FLOOR;
  1589.         c_ptr->pl = FALSE;
  1590.         }
  1591.     } else {
  1592.         /* should become a corridor space */
  1593.         c_ptr->fval = CORR_FLOOR;
  1594.         c_ptr->pl = FALSE;
  1595.     }
  1596.     lite_spot(y, x);
  1597.     res = TRUE;
  1598.     }
  1599.     return (res);
  1600. }
  1601.  
  1602.  
  1603. /* Tunnels through rubble and walls            -RAK-     */
  1604. /* Must take into account: secret doors,  special tools          */
  1605. void 
  1606. tunnel(dir)
  1607. int dir;
  1608. {
  1609.     register int        i, tabil;
  1610.     register cave_type *c_ptr;
  1611.     register inven_type *i_ptr;
  1612.     int                 y, x;
  1613.     monster_type       *m_ptr;
  1614.     vtype               out_val, m_name;
  1615.  
  1616.     if ((py.flags.confused > 0) && /* Confused?         */
  1617.     (randint(4) > 1))       /* 75% random movement   */
  1618.     dir = randint(9);
  1619.     y = char_row;
  1620.     x = char_col;
  1621.     (void)mmove(dir, &y, &x);
  1622.  
  1623.     c_ptr = &cave[y][x];
  1624. /* Compute the digging ability of player; based on       */
  1625. /* strength, and type of tool used               */
  1626.     tabil = py.stats.use_stat[A_STR];
  1627.     i_ptr = &inventory[INVEN_WIELD];
  1628.  
  1629. /* Don't let the player tunnel somewhere illegal, this is necessary to
  1630.  * prevent the player from getting a free attack by trying to tunnel
  1631.  * somewhere where it has no effect.  
  1632.  */
  1633.     if (c_ptr->fval < MIN_CAVE_WALL
  1634.     && (c_ptr->tptr == 0 || (t_list[c_ptr->tptr].tval != TV_RUBBLE
  1635.               && t_list[c_ptr->tptr].tval != TV_SECRET_DOOR))) {
  1636.     if (c_ptr->tptr == 0) {
  1637.         msg_print("Tunnel through what?  Empty air?!?");
  1638.         free_turn_flag = TRUE;
  1639.     } else {
  1640.         msg_print("You can't tunnel through that.");
  1641.         free_turn_flag = TRUE;
  1642.     }
  1643.     return;
  1644.     }
  1645.     if (c_ptr->cptr > 1) {
  1646.     m_ptr = &m_list[c_ptr->cptr];
  1647.     if (m_ptr->ml) {
  1648.         if (c_list[m_ptr->mptr].cdefense & UNIQUE)
  1649.         (void)sprintf(m_name, "%s", c_list[m_ptr->mptr].name);
  1650.         else
  1651.         (void)sprintf(m_name, "The %s", c_list[m_ptr->mptr].name);
  1652.     } else
  1653.         (void)strcpy(m_name, "Something");
  1654.     (void)sprintf(out_val, "%s is in your way!", m_name);
  1655.     msg_print(out_val);
  1656.  
  1657.     /* let the player attack the creature */
  1658.     if (py.flags.afraid < 1)
  1659.         py_attack(y, x);
  1660.     else
  1661.         msg_print("You are too afraid!");
  1662.     } else if (i_ptr->tval != TV_NOTHING) {
  1663.     if (TR_TUNNEL & i_ptr->flags)
  1664.         tabil += 25 + i_ptr->p1 * 50;
  1665.     else {
  1666.         tabil += (i_ptr->damage[0] * i_ptr->damage[1]) + i_ptr->tohit
  1667.         + i_ptr->todam;
  1668.     /* divide by two so that digging without shovel isn't too easy */
  1669.         tabil >>= 1;
  1670.     }
  1671.  
  1672.     if (weapon_heavy) {
  1673.         tabil += (py.stats.use_stat[A_STR] * 15) - i_ptr->weight;
  1674.         if (tabil < 0)
  1675.         tabil = 0;
  1676.     }
  1677.     /* Regular walls; Granite, magma intrusion, quartz vein  */
  1678.     /* Don't forget the boundary walls, made of titanium (255) */
  1679.     switch (c_ptr->fval) {
  1680.       case GRANITE_WALL:
  1681.         i = randint(1200) + 80;
  1682.         if (twall(y, x, tabil, i)) {
  1683.         msg_print("You have finished the tunnel.");
  1684.         check_view();
  1685.         } else
  1686.         count_msg_print("You tunnel into the granite wall.");
  1687.         break;
  1688.       case MAGMA_WALL:
  1689.         i = randint(600) + 10;
  1690.         if (twall(y, x, tabil, i)) {
  1691.         msg_print("You have finished the tunnel.");
  1692.         check_view();
  1693.         } else
  1694.         count_msg_print("You tunnel into the magma intrusion.");
  1695.         break;
  1696.       case QUARTZ_WALL:
  1697.         i = randint(400) + 10;
  1698.         if (twall(y, x, tabil, i)) {
  1699.         msg_print("You have finished the tunnel.");
  1700.         check_view();
  1701.         } else
  1702.         count_msg_print("You tunnel into the quartz vein.");
  1703.         break;
  1704.       case BOUNDARY_WALL:
  1705.         msg_print("This seems to be permanent rock.");
  1706.         break;
  1707.       default:
  1708.     /* Is there an object in the way?  (Rubble and secret doors) */
  1709.         if (c_ptr->tptr != 0) {
  1710.         /* Rubble.     */
  1711.         if (t_list[c_ptr->tptr].tval == TV_RUBBLE) {
  1712.             if (tabil > randint(180)) {
  1713.             (void)delete_object(y, x);
  1714.             msg_print("You have removed the rubble.");
  1715.             if (randint(10) == 1) {
  1716.                 place_object(y, x);
  1717.                 if (test_light(y, x))
  1718.                 msg_print("You have found something!");
  1719.             }
  1720.             lite_spot(y, x);
  1721.             check_view();
  1722.             } else
  1723.             count_msg_print("You dig in the rubble.");
  1724.         }
  1725.         /* Secret doors. */
  1726.         else if (t_list[c_ptr->tptr].tval == TV_SECRET_DOOR) {
  1727.             count_msg_print("You tunnel into the granite wall.");
  1728.             search(char_row, char_col, py.misc.srh);
  1729.         } else {
  1730.             msg_print("You can't tunnel through that.");
  1731.             free_turn_flag = TRUE;
  1732.         }
  1733.         } else {
  1734.         msg_print("Tunnel through what?  Empty air?!?");
  1735.         free_turn_flag = TRUE;
  1736.         }
  1737.         break;
  1738.     }
  1739.     } else
  1740.     msg_print("You dig with your hands, making no progress.");
  1741. }
  1742.  
  1743.  
  1744. /* Disarms a trap                    -RAK-     */
  1745. void 
  1746. disarm_trap()
  1747. {
  1748.     int                 y, x, level, tmp, dir, no_disarm;
  1749.     register int        tot, i;
  1750.     register cave_type *c_ptr;
  1751.     register inven_type *i_ptr;
  1752.     monster_type       *m_ptr;
  1753.     vtype               m_name, out_val;
  1754. #ifdef TARGET
  1755.     int temp = target_mode; /* targetting will screw up get_dir, so we save
  1756.                    target_mode, then turn it off -CFT */
  1757. #endif
  1758.  
  1759.     y = char_row;
  1760.     x = char_col;
  1761. #ifdef TARGET
  1762.     target_mode = FALSE;
  1763. #endif
  1764.     if (get_dir(NULL, &dir)) {
  1765.     (void)mmove(dir, &y, &x);
  1766.     c_ptr = &cave[y][x];
  1767.     no_disarm = FALSE;
  1768.     if (c_ptr->cptr > 1 && c_ptr->tptr != 0 &&
  1769.         (t_list[c_ptr->tptr].tval == TV_VIS_TRAP
  1770.          || t_list[c_ptr->tptr].tval == TV_CHEST)) {
  1771.         m_ptr = &m_list[c_ptr->cptr];
  1772.         if (m_ptr->ml)
  1773.         (void)sprintf(m_name, "The %s", c_list[m_ptr->mptr].name);
  1774.         else
  1775.         (void)strcpy(m_name, "Something");
  1776.         (void)sprintf(out_val, "%s is in your way!", m_name);
  1777.         msg_print(out_val);
  1778.     } else if (c_ptr->tptr != 0) {
  1779.         tot = py.misc.disarm + 2 * todis_adj() + stat_adj(A_INT)
  1780.         + (class_level_adj[py.misc.pclass][CLA_DISARM] * py.misc.lev / 3);
  1781.         if ((py.flags.blind > 0) || (no_light()))
  1782.         tot = tot / 10;
  1783.         if (py.flags.confused > 0)
  1784.         tot = tot / 10;
  1785.         if (py.flags.image > 0)
  1786.         tot = tot / 10;
  1787.         i_ptr = &t_list[c_ptr->tptr];
  1788.         i = i_ptr->tval;
  1789.         level = i_ptr->level;
  1790.         if (i == TV_VIS_TRAP) {/* Floor trap    */
  1791.         if ((tot + 100 - level) > randint(100)) {
  1792.             msg_print("You have disarmed the trap.");
  1793.             py.misc.exp += i_ptr->p1;
  1794.             (void)delete_object(y, x);
  1795.         /* make sure we move onto the trap even if confused */
  1796.             tmp = py.flags.confused;
  1797.             py.flags.confused = 0;
  1798.             move_char(dir, FALSE);
  1799.             py.flags.confused = tmp;
  1800.             prt_experience();
  1801.         }
  1802.         /* avoid randint(0) call */
  1803.         else if ((tot > 5) && (randint(tot) > 5))
  1804.             count_msg_print("You failed to disarm the trap.");
  1805.         else {
  1806.             msg_print("You set the trap off!");
  1807.         /* make sure we move onto the trap even if confused */
  1808.             tmp = py.flags.confused;
  1809.             py.flags.confused = 0;
  1810.             move_char(dir, FALSE);
  1811.             py.flags.confused += tmp;
  1812.         }
  1813.         } else if (i == TV_CHEST) {
  1814.         if (!known2_p(i_ptr)) {
  1815.             msg_print("I don't see a trap.");
  1816.             free_turn_flag = TRUE;
  1817.         } else if (CH_TRAPPED & i_ptr->flags) {
  1818.             if ((tot - level) > randint(100)) {
  1819.             i_ptr->flags &= ~CH_TRAPPED;
  1820.             if (CH_LOCKED & i_ptr->flags)
  1821.                 i_ptr->name2 = SN_LOCKED;
  1822.             else
  1823.                 i_ptr->name2 = SN_DISARMED;
  1824.             msg_print("You have disarmed the chest.");
  1825.             known2(i_ptr);
  1826.             py.misc.exp += level;
  1827.             prt_experience();
  1828.             } else if ((tot > 5) && (randint(tot) > 5))
  1829.             count_msg_print("You failed to disarm the chest.");
  1830.             else {
  1831.             msg_print("You set a trap off!");
  1832.             known2(i_ptr);
  1833.             chest_trap(y, x);
  1834.             }
  1835.         } else {
  1836.             msg_print("The chest was not trapped.");
  1837.             free_turn_flag = TRUE;
  1838.         }
  1839.         } else
  1840.         no_disarm = TRUE;
  1841.     } else
  1842.         no_disarm = TRUE;
  1843.  
  1844.     if (no_disarm) {
  1845.         msg_print("I do not see anything to disarm there.");
  1846.         free_turn_flag = TRUE;
  1847.     }
  1848.     }
  1849. #ifdef TARGET
  1850.     target_mode = temp;
  1851. #endif
  1852. }
  1853.  
  1854.  
  1855. /* An enhanced look, with peripheral vision. Looking all 8    -CJS-
  1856.  * directions will see everything which ought to be visible. Can specify
  1857.  * direction 5, which looks in all directions. 
  1858.  *
  1859.  * For the purpose of hindering vision, each place is regarded as a diamond just
  1860.  * touching its four immediate neighbours. A diamond is opaque if it is a
  1861.  * wall, or shut door, or something like that. A place is visible if any part
  1862.  * of its diamond is visible: i.e. there is a line from the view point to
  1863.  * part of the diamond which does not pass through any opaque diamonds. 
  1864.  *
  1865.  * Consider the following situation: 
  1866.  *
  1867.  * @....                X    X   X    X   X .##..               /
  1868.  * \ / \ / \ / \ / \ .....              X @ X . X . X 1 X . X \ / \
  1869.  * / \ / \ / \ / X    X   X    X   X Expanded view, with       / \ / \ /
  1870.  * \ / \ / \ diamonds inscribed      X . X # X # X 2 X . X about each point,      
  1871.  * \ / \ / \ / \ / \ / and some locations        X    X   X    X   X
  1872.  * numbered.           / \ / \ / \ / \ / \ X . X . X . X 3 X 4 X \ / \ /
  1873.  * \ / \ / \ / X    X   X    X   X - Location 1 is fully visible. -
  1874.  * Location 2 is visible, even though partially obscured. - Location 3 is
  1875.  * invisible, but if either # were transparent, it would be visible. -
  1876.  * Location 4 is completely obscured by a single #. 
  1877.  *
  1878.  * The function which does the work is look_ray. It sets up its own co-ordinate
  1879.  * frame (global variables map back to the dungeon frame) and looks for
  1880.  * everything between two angles specified from a central line. It is
  1881.  * recursive, and each call looks at stuff visible along a line parallel to
  1882.  * the center line, and a set distance away from it. A diagonal look uses
  1883.  * more extreme peripheral vision from the closest horizontal and vertical
  1884.  * directions; horizontal or vertical looks take a call for each side of the
  1885.  * central line. 
  1886.  */
  1887.  
  1888. /*
  1889.  * Globally accessed variables: gl_nseen counts the number of places where
  1890.  * something is seen. gl_rock indicates a look for rock or objects. 
  1891.  *
  1892.  * The others map co-ords in the ray frame to dungeon co-ords. 
  1893.  *
  1894.  * dungeon y = char_row     + gl_fyx * (ray x)  + gl_fyy * (ray y) dungeon x =
  1895.  * char_col     + gl_fxx * (ray x)  + gl_fxy * (ray y) 
  1896.  */
  1897. static int gl_fxx, gl_fxy, gl_fyx, gl_fyy;
  1898. static int gl_nseen, gl_noquery;
  1899. static int gl_rock;
  1900.  
  1901. /*
  1902.  * Intended to be indexed by dir/2, since is only relevant to horizontal or
  1903.  * vertical directions. 
  1904.  */
  1905. static int set_fxy[] = {0, 1, 0, 0, -1};
  1906. static int set_fxx[] = {0, 0, -1, 1, 0};
  1907. static int set_fyy[] = {0, 0, 1, -1, 0};
  1908. static int set_fyx[] = {0, 1, 0, 0, -1};
  1909.  
  1910. /* Map diagonal-dir/2 to a normal-dir/2. */
  1911. static int map_diag1[] = {1, 3, 0, 2, 4};
  1912. static int map_diag2[] = {2, 1, 0, 4, 3};
  1913.  
  1914. #define GRADF    10000           /* Any sufficiently big number will do */
  1915.  
  1916. /*
  1917.  * Look at what we can see. This is a free move. 
  1918.  *
  1919.  * Prompts for a direction, and then looks at every object in turn within a cone
  1920.  * of vision in that direction. For each object, the cursor is moved over the
  1921.  * object, a description is given, and we wait for the user to type
  1922.  * something. Typing ESCAPE will abort the entire look. 
  1923.  *
  1924.  * Looks first at real objects and monsters, and looks at rock types only after
  1925.  * all other things have been seen.  Only looks at rock types if the
  1926.  * highlight_seams option is set. 
  1927.  */
  1928.  
  1929. void 
  1930. look()
  1931. {
  1932.     register int        i, abort;
  1933.     int                 dir, dummy;
  1934.  
  1935.     if (py.flags.blind > 0)
  1936.     msg_print("You can't see a damn thing!");
  1937.     else if (py.flags.image > 0)
  1938.     msg_print("You can't believe what you are seeing! It's like a dream!");
  1939.     else if (get_alldir("Look which direction? ", &dir)) {
  1940.     abort = FALSE;
  1941.     gl_nseen = 0;
  1942.     gl_rock = 0;
  1943.     gl_noquery = FALSE;       /* Have to set this up for the look_see */
  1944.     if (look_see(0, 0, &dummy))
  1945.         abort = TRUE;
  1946.     else {
  1947.         do {
  1948.         abort = FALSE;
  1949.         if (dir == 5) {
  1950.             for (i = 1; i <= 4; i++) {
  1951.             gl_fxx = set_fxx[i];
  1952.             gl_fyx = set_fyx[i];
  1953.             gl_fxy = set_fxy[i];
  1954.             gl_fyy = set_fyy[i];
  1955.             if (look_ray(0, 2 * GRADF - 1, 1)) {
  1956.                 abort = TRUE;
  1957.                 break;
  1958.             }
  1959.             gl_fxy = (-gl_fxy);
  1960.             gl_fyy = (-gl_fyy);
  1961.             if (look_ray(0, 2 * GRADF, 2)) {
  1962.                 abort = TRUE;
  1963.                 break;
  1964.             }
  1965.             }
  1966.         } else if ((dir & 1) == 0) {    /* Straight directions */
  1967.             i = dir >> 1;
  1968.             gl_fxx = set_fxx[i];
  1969.             gl_fyx = set_fyx[i];
  1970.             gl_fxy = set_fxy[i];
  1971.             gl_fyy = set_fyy[i];
  1972.             if (look_ray(0, GRADF, 1))
  1973.             abort = TRUE;
  1974.             else {
  1975.             gl_fxy = (-gl_fxy);
  1976.             gl_fyy = (-gl_fyy);
  1977.             abort = look_ray(0, GRADF, 2);
  1978.             }
  1979.         } else {
  1980.             i = map_diag1[dir >> 1];
  1981.             gl_fxx = set_fxx[i];
  1982.             gl_fyx = set_fyx[i];
  1983.             gl_fxy = (-set_fxy[i]);
  1984.             gl_fyy = (-set_fyy[i]);
  1985.             if (look_ray(1, 2 * GRADF, GRADF))
  1986.             abort = TRUE;
  1987.             else {
  1988.             i = map_diag2[dir >> 1];
  1989.             gl_fxx = set_fxx[i];
  1990.             gl_fyx = set_fyx[i];
  1991.             gl_fxy = set_fxy[i];
  1992.             gl_fyy = set_fyy[i];
  1993.             abort = look_ray(1, 2 * GRADF - 1, GRADF);
  1994.             }
  1995.         }
  1996.         }
  1997.         while (abort == FALSE && highlight_seams && (++gl_rock < 2));
  1998.         if (abort)
  1999.         msg_print("--Aborting look--");
  2000.         else {
  2001.         if (gl_nseen) {
  2002.             if (dir == 5)
  2003.             msg_print("That's all you see.");
  2004.             else
  2005.             msg_print("That's all you see in that direction.");
  2006.         } else if (dir == 5)
  2007.             msg_print("You see nothing of interest.");
  2008.         else
  2009.             msg_print("You see nothing of interest in that direction.");
  2010.         }
  2011.     }
  2012.     }
  2013. }
  2014.  
  2015. /* Look at everything within a cone of vision between two ray
  2016.    lines emanating from the player, and y or more places away
  2017.    from the direct line of view. This is recursive.
  2018.  
  2019.    Rays are specified by gradients, y over x, multiplied by
  2020.    2*GRADF. This is ONLY called with gradients between 2*GRADF
  2021.    (45 degrees) and 1 (almost horizontal).
  2022.  
  2023.    (y axis)/ angle from
  2024.      ^      /        ___ angle to
  2025.      |     /     ___
  2026.   ...|../.....___.................... parameter y (look at things in the
  2027.      | /   ___                  cone, and on or above this line)
  2028.      |/ ___
  2029.      @-------------------->   direction in which you are looking. (x axis)
  2030.      |
  2031.      | */
  2032.  
  2033. static int 
  2034. look_ray(y, from, to)
  2035. int y, from, to;
  2036. {
  2037.     register int        max_x, x;
  2038.     int                 transparent;
  2039.  
  2040. /* from is the larger angle of the ray, since we scan towards the center
  2041.  * line. If from is smaller, then the ray does not exist. 
  2042.  */
  2043.     if (from <= to || y > MAX_SIGHT)
  2044.     return FALSE;
  2045. /* Find first visible location along this line. Minimum x such that (2x-1)/x
  2046.  * < from/GRADF <=> x > GRADF(2x-1)/from. This may be called with y=0 whence
  2047.  * x will be set to 0. Thus we need a special fix. 
  2048.  */
  2049.     x = (long)GRADF    *(2 * y - 1) / from + 1;
  2050.  
  2051.     if (x <= 0)
  2052.     x = 1;
  2053.  
  2054. /* Find last visible location along this line. Maximum x such that (2x+1)/x >
  2055.  * to/GRADF <=> x < GRADF(2x+1)/to 
  2056.  */
  2057.     max_x = ((long)GRADF * (2 * y + 1) - 1) / to;
  2058.     if (max_x > MAX_SIGHT)
  2059.     max_x = MAX_SIGHT;
  2060.     if (max_x < x)
  2061.     return FALSE;
  2062.  
  2063. /* gl_noquery is a HACK to prevent doubling up on direct lines of sight. If
  2064.  * 'to' is    greater than 1, we do not really look at stuff along the
  2065.  * direct line of sight, but we do have to see what is opaque for the
  2066.  * purposes of obscuring other objects. 
  2067.  */
  2068.     if ((y == 0 && to > 1) || (y == x && from < GRADF * 2))
  2069.     gl_noquery = TRUE;
  2070.     else
  2071.     gl_noquery = FALSE;
  2072.     if (look_see(x, y, &transparent))
  2073.     return TRUE;
  2074.     if (y == x)
  2075.     gl_noquery = FALSE;
  2076.     if (transparent)
  2077.     goto init_transparent;
  2078.  
  2079.     for (;;) {
  2080.     /* Look down the window we've found. */
  2081.     if (look_ray(y + 1, from, (int)((2 * y + 1) * (long)GRADF / x)))
  2082.         return TRUE;
  2083.     /* Find the start of next window. */
  2084.     do {
  2085.         if (x == max_x)
  2086.         return FALSE;
  2087.     /* See if this seals off the scan. (If y is zero, then it will.) */
  2088.         from = (2 * y - 1) * (long)GRADF / x;
  2089.         if (from <= to)
  2090.         return FALSE;
  2091.         x++;
  2092.         if (look_see(x, y, &transparent))
  2093.         return TRUE;
  2094.     }
  2095.     while (!transparent);
  2096. init_transparent:
  2097.     /* Find the end of this window of visibility. */
  2098.     do {
  2099.         if (x == max_x)
  2100.         /* The window is trimmed by an earlier limit. */
  2101.         return look_ray(y + 1, from, to);
  2102.         x++;
  2103.         if (look_see(x, y, &transparent))
  2104.         return TRUE;
  2105.     }
  2106.     while (transparent);
  2107.     }
  2108. }
  2109.  
  2110.  
  2111. static int 
  2112. look_see(x, y, transparent)
  2113. register int        x, y;
  2114. int                *transparent;
  2115. {
  2116.     const char         *dstring,*string;
  2117.     char               query = 'a';
  2118.     register cave_type *c_ptr;
  2119.     register int        j;
  2120.     bigvtype            out_val, tmp_str;
  2121.  
  2122.     if (x < 0 || y < 0 || y > x) {
  2123.     (void)sprintf(tmp_str, "Illegal call to look_see(%d, %d)", x, y);
  2124.     msg_print(tmp_str);
  2125.     }
  2126.     if (x == 0 && y == 0)
  2127.     dstring = "You are on";
  2128.     else
  2129.     dstring = "You see";
  2130.     j = char_col + gl_fxx * x + gl_fxy * y;
  2131.     y = char_row + gl_fyx * x + gl_fyy * y;
  2132.     x = j;
  2133.     if (!panel_contains(y, x)) {
  2134.     *transparent = FALSE;
  2135.     return FALSE;
  2136.     }
  2137.     c_ptr = &cave[y][x];
  2138.     *transparent = c_ptr->fval <= MAX_OPEN_SPACE;
  2139.     if (gl_noquery)
  2140.     return FALSE;           /* Don't look at a direct line of sight. A
  2141.                     * hack. */
  2142.     out_val[0] = 0;
  2143.     if (gl_rock == 0 && c_ptr->cptr > 1 && m_list[c_ptr->cptr].ml) {
  2144.     j = m_list[c_ptr->cptr].mptr;
  2145.     if (c_list[j].cdefense & UNIQUE)
  2146.         (void)sprintf(out_val, "%s %s (%s).  [(r)ecall]",
  2147.               dstring,
  2148.               c_list[j].name,
  2149.               look_mon_desc((int)c_ptr->cptr));
  2150.     else
  2151.         (void)sprintf(out_val, "%s %s %s (%s).  [(r)ecall]",
  2152.               dstring,
  2153.               (is_a_vowel(c_list[j].name[0]) ? "an" : "a"),
  2154.               c_list[j].name,
  2155.               look_mon_desc((int)c_ptr->cptr));
  2156.     dstring = "It is on";
  2157.     prt(out_val, 0, 0);
  2158.     move_cursor_relative(y, x);
  2159.     query = inkey();
  2160.     if (query == 'r' || query == 'R') {
  2161.         save_screen();
  2162.         query = roff_recall(j);
  2163.         restore_screen();
  2164.     }
  2165.     }
  2166.     if (c_ptr->tl || c_ptr->pl || c_ptr->fm) {
  2167.     if (c_ptr->tptr != 0) {
  2168.         if (t_list[c_ptr->tptr].tval == TV_SECRET_DOOR)
  2169.         goto granite;
  2170.         if (gl_rock == 0 && t_list[c_ptr->tptr].tval != TV_INVIS_TRAP) {
  2171.         objdes(tmp_str, &t_list[c_ptr->tptr], TRUE);
  2172.         (void)sprintf(out_val, "%s %s.  ---pause---", dstring, tmp_str);
  2173.         dstring = "It is in";
  2174.         prt(out_val, 0, 0);
  2175.         move_cursor_relative(y, x);
  2176.         query = inkey();
  2177.         }
  2178.     }
  2179.     if ((gl_rock || out_val[0]) && c_ptr->fval >= MIN_CLOSED_SPACE) {
  2180.         switch (c_ptr->fval) {
  2181.           case BOUNDARY_WALL:
  2182.           case GRANITE_WALL:
  2183.     granite:
  2184.         /* Granite is only interesting if it contains something. */
  2185.         if (out_val[0])
  2186.             string = "a granite wall";
  2187.         else
  2188.             string = NULL; /* In case we jump here */
  2189.         break;
  2190.           case MAGMA_WALL:
  2191.         string = "some dark rock";
  2192.         break;
  2193.           case QUARTZ_WALL:
  2194.         string = "a quartz vein";
  2195.         break;
  2196.           default:
  2197.         string = NULL;
  2198.         break;
  2199.         }
  2200.         if (string) {
  2201.         (void)sprintf(out_val, "%s %s.  ---pause---", dstring, string);
  2202.         prt(out_val, 0, 0);
  2203.         move_cursor_relative(y, x);
  2204.         query = inkey();
  2205.         }
  2206.     }
  2207.     }
  2208.     if (out_val[0]) {
  2209.     gl_nseen++;
  2210.     if (query == ESCAPE)
  2211.         return TRUE;
  2212.     }
  2213.     return FALSE;
  2214. }
  2215.  
  2216.  
  2217. static void 
  2218. inven_throw(item_val, t_ptr)
  2219. int         item_val;
  2220. inven_type *t_ptr;
  2221. {
  2222.     register inven_type *i_ptr;
  2223.  
  2224.     i_ptr = &inventory[item_val];
  2225.     *t_ptr = *i_ptr;
  2226.     if (i_ptr->number > 1) {
  2227.     t_ptr->number = 1;
  2228.     i_ptr->number--;
  2229.     inven_weight -= i_ptr->weight;
  2230.     py.flags.status |= PY_STR_WGT;
  2231.     } else
  2232.     inven_destroy(item_val);
  2233. }
  2234.  
  2235.  
  2236. /* Obtain the hit and damage bonuses and the maximum distance for a thrown
  2237.  * missile. 
  2238.  */
  2239. static void 
  2240. facts(i_ptr, tbth, tpth, tdam, tdis, thits)
  2241.     register inven_type *i_ptr;
  2242.     int                 *tbth, *tpth, *tdam, *tdis, *thits;
  2243. {
  2244.     register int        tmp_weight;
  2245.  
  2246.     if (i_ptr->weight < 1)
  2247.     tmp_weight = 1;
  2248.     else
  2249.     tmp_weight = i_ptr->weight;
  2250.  
  2251. /* Throwing objects             */
  2252.     *tdam = pdamroll(i_ptr->damage) + i_ptr->todam;
  2253.     *tbth = py.misc.bthb * 75 / 100;
  2254.     *tpth = py.misc.ptohit + i_ptr->tohit;
  2255.  
  2256. /* Add this back later if the correct throwing device. -CJS- */
  2257.     if (inventory[INVEN_WIELD].tval != TV_NOTHING)
  2258.     *tpth -= inventory[INVEN_WIELD].tohit;
  2259.  
  2260.     *tdis = (((py.stats.use_stat[A_STR] + 20) * 10) / tmp_weight);
  2261.     if (*tdis > 10)
  2262.     *tdis = 10;
  2263.  
  2264. /* EAM - Default to single shot or throw but rangers do better with any kind
  2265.  * of bow 
  2266.  */
  2267.     *thits = 1;
  2268.  
  2269. /* multiply damage bonuses instead of adding, when have proper missile/weapon
  2270.  * combo, this makes them much more useful 
  2271.  */
  2272.  
  2273. /* Using Bows,  slings,  or crossbows     */
  2274.     if (inventory[INVEN_WIELD].tval == TV_BOW)
  2275.     switch (inventory[INVEN_WIELD].subval) {
  2276.       case 20:
  2277.         if (i_ptr->tval == TV_SLING_AMMO) {    /* Sling and ammo */
  2278.         *tbth = py.misc.bthb;
  2279.         *tpth += 2 * inventory[INVEN_WIELD].tohit;
  2280.         *tdam += inventory[INVEN_WIELD].todam;
  2281.         *tdam = *tdam * 2;
  2282.         *tdis = 20;
  2283.         }
  2284.         break;
  2285.       case 21:
  2286.         if (i_ptr->tval == TV_SLING_AMMO){ /* Sling of Might and ammo */
  2287.         *tbth = py.misc.bthb;
  2288.         *tpth += 2 * inventory[INVEN_WIELD].tohit;
  2289.         *tdam += inventory[INVEN_WIELD].todam;
  2290.         *tdam = *tdam * 3;
  2291.         *tdis = 20;
  2292.         }
  2293.         break;
  2294.       case 1:
  2295.         if (i_ptr->tval == TV_ARROW) {    /* Short Bow and Arrow     */
  2296.         *tbth = py.misc.bthb;
  2297.         *tpth += 2 * inventory[INVEN_WIELD].tohit;
  2298.         *tdam += inventory[INVEN_WIELD].todam;
  2299.         *tdam = *tdam * 2;
  2300.         *tdis = 25;
  2301.         }
  2302.         break;
  2303.       case 2:
  2304.         if (i_ptr->tval == TV_ARROW) {    /* Long Bow and Arrow     */
  2305.         *tbth = py.misc.bthb;
  2306.         *tpth += 2 * inventory[INVEN_WIELD].tohit;
  2307.         *tdam += inventory[INVEN_WIELD].todam;
  2308.         *tdam = *tdam * 3;
  2309.         *tdis = 30;
  2310.         }
  2311.         break;
  2312.       case 3:
  2313.         if (i_ptr->tval == TV_ARROW){   /* C Bow, BARD, L bow of M and Arrow*/
  2314.         *tbth = py.misc.bthb;
  2315.         *tpth += 2 * inventory[INVEN_WIELD].tohit;
  2316.         *tdam += inventory[INVEN_WIELD].todam;
  2317.         *tdam = *tdam * 4;
  2318.         *tdis = 35;
  2319.         }
  2320.         break;
  2321.       case 4:
  2322.         if (i_ptr->tval == TV_ARROW){   /* C Bow of M, BELEG and Arrow*/
  2323.         *tbth = py.misc.bthb;
  2324.         *tpth += 2 * inventory[INVEN_WIELD].tohit;
  2325.         *tdam += inventory[INVEN_WIELD].todam;
  2326.         *tdam = *tdam * 5;
  2327.         *tdis = 35;
  2328.         }
  2329.         break;        
  2330.       case 10:
  2331.         if (i_ptr->tval == TV_BOLT) {    /* Light Crossbow and Bolt */
  2332.         *tbth = py.misc.bthb;
  2333.         *tpth += 2 * inventory[INVEN_WIELD].tohit;
  2334.         *tdam += inventory[INVEN_WIELD].todam;
  2335.         *tdam = *tdam * 3;
  2336.         *tdis = 25;
  2337.         }
  2338.         break;
  2339.       case 11:
  2340.         if (i_ptr->tval == TV_BOLT) {    /* Heavy Crossbow and Bolt */
  2341.         *tbth = py.misc.bthb;
  2342.         *tpth += 2 * inventory[INVEN_WIELD].tohit;
  2343.         *tdam += inventory[INVEN_WIELD].todam;
  2344.         *tdam = *tdam * 4;
  2345.         *tdis = 35;
  2346.         }
  2347.         break;
  2348.       case 12:
  2349.         if (i_ptr->tval == TV_BOLT){    /* H xbow of M and Bolt*/
  2350.         *tbth = py.misc.bthb;
  2351.         *tpth += 2 * inventory[INVEN_WIELD].tohit;
  2352.         *tdam += inventory[INVEN_WIELD].todam;
  2353.         *tdam = *tdam * 5;
  2354.         *tdis = 35;
  2355.         }
  2356.         break;
  2357.         
  2358.     }
  2359. }
  2360.  
  2361.  
  2362. static void 
  2363. drop_throw(y, x, t_ptr)
  2364. int                 y, x;
  2365. inven_type         *t_ptr;
  2366. {
  2367.     register int i, j, k;
  2368.     int flag, cur_pos;
  2369.     bigvtype out_val, tmp_str;
  2370.     register cave_type *c_ptr;
  2371.  
  2372.     flag = FALSE;
  2373.     i = y;
  2374.     j = x;
  2375.     k = 0;
  2376.     if (randint(5) > 1) {
  2377.     do {
  2378.         if (in_bounds(i, j)) {
  2379.         c_ptr = &cave[i][j];
  2380.         if (c_ptr->fval <= MAX_OPEN_SPACE && c_ptr->tptr == 0)
  2381.             flag = TRUE;
  2382.         }
  2383.         if (!flag) {
  2384.         i = y + randint(3) - 2;
  2385.         j = x + randint(3) - 2;
  2386.         k++;
  2387.         }
  2388.     }
  2389.     while ((!flag) && (k <= 9));
  2390.     }
  2391.     if (!flag && (t_ptr->tval >= TV_MIN_WEAR) &&
  2392.     (t_ptr->tval <= TV_MAX_WEAR) && (t_ptr->flags2 & TR_ARTIFACT)) {
  2393.     k = 0;  i = y;  j = x;
  2394.     do {        /* pick place w/o an object, unless doesn't seem to be one */
  2395.         y = i;  x = j;
  2396.         do {        /* pick place in bounds and not in wall */
  2397.         i = y + randint(3) -2;
  2398.         j = x + randint(3) -2;
  2399.         } while (!in_bounds(i,j) || cave[i][j].fval > MAX_OPEN_SPACE);
  2400.         k++;
  2401.         if (!(cur_pos = cave[i][j].tptr) || (k>64))
  2402.         flag = TRUE;
  2403.         if (flag && (((t_list[cur_pos].flags2 & TR_ARTIFACT) &&
  2404.               ((cur_pos = t_list[cur_pos].tval) >= TV_MIN_WEAR) &&
  2405.               (cur_pos <= TV_MAX_WEAR)) ||
  2406.              (cur_pos == TV_STORE_DOOR) ||
  2407.              (cur_pos == TV_UP_STAIR) ||
  2408.              (cur_pos == TV_DOWN_STAIR)))
  2409.         flag = FALSE;
  2410. /* the above may seem convoluted, but it basically says: try up to 64 spaces,
  2411.  * if an open one, place the item.  If none, clobber the item at 64th, but keep looking
  2412.  * if that item is an artifact, store door, or stairs -CFT
  2413.  */
  2414.         
  2415.         if (k>888) flag = TRUE; /* if this many tries, TOO BAD! -CFT */
  2416.     } while (!flag);
  2417.     } /* if not flag and is artifact */
  2418.     if (flag)
  2419.     {
  2420.     if (cave[i][j].tptr)    /* we must have crushed something; waste it -CFT */
  2421.         delete_object(i,j);
  2422.     cur_pos = popt();
  2423.     cave[i][j].tptr = cur_pos;
  2424.     t_list[cur_pos] = *t_ptr;
  2425.     lite_spot(i, j);
  2426.     }
  2427.     else
  2428.     {
  2429.     objdes(tmp_str, t_ptr, FALSE);
  2430.     (void) sprintf(out_val, "The %s disappears.", tmp_str);
  2431.     msg_print(out_val);
  2432.     }
  2433. }
  2434.  
  2435. /* This is another adaptation of DGK's Fangband code to help throw item
  2436.    stay around (like Artifacts!) -CFT */
  2437. static int
  2438. stays_when_throw(i_ptr)
  2439. inven_type *i_ptr;
  2440. {
  2441.   if ((i_ptr->tval >= TV_MIN_WEAR) && (i_ptr->tval <= TV_MAX_WEAR) &&
  2442.       (i_ptr->flags2 & TR_ARTIFACT))
  2443.     return TRUE;
  2444.  
  2445.   /* for non-artifacts, drop_throw() still loses 20% of them... */
  2446.   if ((i_ptr->tval >= TV_BOW) && (i_ptr->tval <= TV_STAFF))
  2447.     return TRUE;
  2448.   switch (i_ptr->tval){
  2449.     case TV_CHEST: case TV_SLING_AMMO: case TV_ROD: case TV_FOOD:
  2450.     case TV_MAGIC_BOOK: case TV_PRAYER_BOOK:
  2451.       return TRUE;
  2452.     case TV_MISC: case TV_SPIKE: case TV_WAND: case TV_BOLT:
  2453.     case TV_ARROW: case TV_LIGHT: case TV_SCROLL1: case TV_SCROLL2:
  2454.       return (randint(2)==1);
  2455.   }
  2456.   return FALSE;
  2457. }
  2458.  
  2459.  
  2460.  
  2461. /* Throw an object across the dungeon.        -RAK-     */
  2462. /* Note: Flasks of oil do fire damage                 */
  2463. /* Note: Extra damage and chance of hitting when missiles are used */
  2464. /* with correct weapon.  I.E.  wield bow and throw arrow.     */
  2465. /* Note: Some characters will now get multiple shots per turn -EAM */
  2466. void 
  2467. throw_object()
  2468. {
  2469.     int item_val, tbth, tpth, tdam, tdis;
  2470.     int y, x, oldy, oldx, cur_dis, dir;
  2471.     int flag, visible;
  2472.     int thits, max_shots;
  2473.     int ok_throw = FALSE; /* used to prompt user with, so doesn't throw wrong thing */
  2474.     bigvtype            out_val, tmp_str;
  2475.     inven_type          throw_obj;
  2476.     register cave_type *c_ptr;
  2477.     register monster_type *m_ptr;
  2478.     register int        i;
  2479.     char                tchar;
  2480.  
  2481.     if (inven_ctr == 0) {
  2482.     msg_print("But you are not carrying anything.");
  2483.     free_turn_flag = TRUE;
  2484.     } else if (get_item(&item_val, "Fire/Throw which one?", 0, inven_ctr - 1, 0)) {
  2485.     inven_type *t = &inventory[item_val];
  2486.     
  2487.     if ((t->tval == TV_FLASK) || (t->tval == TV_SLING_AMMO) ||
  2488.         (t->tval == TV_ARROW) || (t->tval == TV_BOLT) ||
  2489.         (t->tval == TV_SPIKE) || (t->tval == TV_MISC))
  2490.         ok_throw = TRUE;
  2491.     else if (((t->tval == TV_FOOD) || (t->tval == TV_POTION1) ||
  2492.           (t->tval == TV_POTION2)) && known1_p(t) &&
  2493.          /* almost all potions do 1d1 damage when thrown.  I want the code
  2494.             to ask before throwing away potions of DEX, *Healing*, etc.
  2495.             This also means it will ask before throwing potions of slow
  2496.             poison, and other low value items that the player is likely to
  2497.             not care about.  This code will mean that mushrooms/molds of
  2498.             unhealth, potions of detonations and death are the only
  2499.             always-throwable food/potions.  (plus known bad ones, in a
  2500.             later test...) -CFT */
  2501.          (t->damage[0] > 1) && (t->damage[1] > 1))
  2502.         ok_throw = TRUE; /* if it's a mushroom or potion that does
  2503.                                 damage when thrown... */
  2504.     else if (!known2_p(t) && (t->ident & ID_DAMD))
  2505.         ok_throw = TRUE;  /* Not IDed, but user knows it's cursed... */
  2506.     else if ((t->tval >= TV_MIN_WEAR) && (t->tval <= TV_MAX_WEAR) &&
  2507.          (t->flags & TR_CURSED) && known2_p(t))
  2508.         ok_throw = TRUE; /* if user wants to throw cursed, let him */
  2509.     else if ((object_list[t->index].cost <= 0) && known1_p(t) &&
  2510.          !(known2_p(t) && (t->cost > 0)))
  2511.         ok_throw = TRUE;
  2512.     else if ((t->cost <= 0) && known2_p(t))
  2513.         ok_throw = TRUE; /* it's junk, let him throw it */
  2514.     else if ((t->tval >= TV_HAFTED) &&
  2515.          (t->tval <= TV_DIGGING) && !(t->name2))
  2516.         ok_throw = TRUE; /* non ego/art weapons are okay to just throw, since
  2517.                 they are damaging (Moral of story: wield your weapon
  2518.                 if you're worried that you might throw it away!) */
  2519.     else { /* otherwise double-check with user before throwing -CFT */
  2520.         objdes(tmp_str, t, TRUE);
  2521.         sprintf(out_val, "Really throw %s?", tmp_str);
  2522.         ok_throw = get_check(out_val);
  2523.     }
  2524.     } /* if selected an item to throw */
  2525.  
  2526.     if (ok_throw) { /* can only be true if selected item, and it either looked
  2527.              * okay, or user said yes... */
  2528.     if (get_dir(NULL, &dir)) {
  2529.         desc_remain(item_val);
  2530.         if (py.flags.confused > 0) {
  2531.         msg_print("You are confused.");
  2532.         do {
  2533.             dir = randint(9);
  2534.         }
  2535.         while (dir == 5);
  2536.         }
  2537.         max_shots = inventory[item_val].number;
  2538.         inven_throw(item_val, &throw_obj);
  2539.         facts(&throw_obj, &tbth, &tpth, &tdam, &tdis, &thits);
  2540.         if (thits > max_shots)
  2541.         thits = max_shots;
  2542.         tchar = throw_obj.tchar;
  2543.     /* EAM Start loop over multiple shots */
  2544.         while (thits-- > 0) {
  2545.         if (inventory[INVEN_WIELD].subval == 12)
  2546.             tpth -= 10;
  2547.         flag = FALSE;
  2548.         y = char_row;
  2549.         x = char_col;
  2550.         oldy = char_row;
  2551.         oldx = char_col;
  2552.         cur_dis = 0;
  2553.         do {
  2554.             (void)mmove(dir, &y, &x);
  2555.             cur_dis++;
  2556.             lite_spot(oldy, oldx);
  2557.             if (cur_dis > tdis)
  2558.             flag = TRUE;
  2559.             c_ptr = &cave[y][x];
  2560.             if ((c_ptr->fval <= MAX_OPEN_SPACE) && (!flag)) {
  2561.             if (c_ptr->cptr > 1) {
  2562.                 flag = TRUE;
  2563.                 m_ptr = &m_list[c_ptr->cptr];
  2564.                 tbth = tbth - cur_dis;
  2565.             /* if monster not lit, make it much more difficult to
  2566.              * hit, subtract off most bonuses, and reduce bthb
  2567.              * depending on distance 
  2568.              */
  2569.                 if (!m_ptr->ml)
  2570.                 tbth = (tbth / (cur_dis + 2))
  2571.                     - (py.misc.lev *
  2572.                        class_level_adj[py.misc.pclass][CLA_BTHB] / 2)
  2573.                     - (tpth * (BTH_PLUS_ADJ - 1));
  2574.                 if (test_hit(tbth, (int)py.misc.lev, tpth,
  2575.                    (int)c_list[m_ptr->mptr].ac, CLA_BTHB)) {
  2576.                 i = m_ptr->mptr;
  2577.                 objdes(tmp_str, &throw_obj, FALSE);
  2578.                 /* Does the player know what he's fighting?       */
  2579.                 if (!m_ptr->ml) {
  2580.                     (void)sprintf(out_val,
  2581.                        "The %s finds a mark.", tmp_str);
  2582.                     visible = FALSE;
  2583.                 } else {
  2584.                     if (c_list[i].cdefense & UNIQUE)
  2585.                     (void)sprintf(out_val, "The %s hits %s.",
  2586.                            tmp_str, c_list[i].name);
  2587.                     else
  2588.                     (void)sprintf(out_val, "The %s hits the %s.",
  2589.                            tmp_str, c_list[i].name);
  2590.                     visible = TRUE;
  2591.                 }
  2592.                 msg_print(out_val);
  2593.                 tdam = tot_dam(&throw_obj, tdam, i);
  2594.                 tdam = critical_blow((int)throw_obj.weight,
  2595.                              tpth, tdam, CLA_BTHB);
  2596.                 if (tdam < 0)
  2597.                     tdam = 0;
  2598.                 /*
  2599.                  * always print fear msgs, so player can stop
  2600.                  * shooting -CWS 
  2601.                  */
  2602.                 i = mon_take_hit((int)c_ptr->cptr, tdam, TRUE);
  2603.                 if (i < 0) {
  2604.                     char                buf[100];
  2605.                     char                cdesc[100];
  2606.                     if (visible) {
  2607.                     if (c_list[i].cdefense & UNIQUE)
  2608.                         sprintf(cdesc, "%s", c_list[m_ptr->mptr].name);
  2609.                     else
  2610.                         sprintf(cdesc, "The %s", c_list[m_ptr->mptr].name);
  2611.                     } else
  2612.                     strcpy(cdesc, "It");
  2613.                     (void)sprintf(buf,
  2614.                           pain_message((int)c_ptr->cptr,
  2615.                                    (int)tdam), cdesc);
  2616.                     msg_print(buf);
  2617.                 }
  2618.                 if (i >= 0) {
  2619.                     if (!visible)
  2620.                     msg_print("You have killed something!");
  2621.                     else {
  2622.                     if (c_list[i].cdefense & UNIQUE)
  2623.                         (void)sprintf(out_val, "You have killed %s.",
  2624.                               c_list[i].name);
  2625.                     else
  2626.                         (void)sprintf(out_val, "You have killed the %s.",
  2627.                               c_list[i].name);
  2628.                     msg_print(out_val);
  2629.                     }
  2630.                     prt_experience();
  2631.                 }
  2632.                 if (stays_when_throw(&throw_obj))
  2633. /* should it land on floor?  Or else vanish forever? */
  2634.                     drop_throw(oldy, oldx, &throw_obj);
  2635.                 }
  2636.                 else
  2637.                 drop_throw(oldy, oldx, &throw_obj);
  2638.             }
  2639.             else
  2640.             {   /* do not test c_ptr->fm here */
  2641.                 if (panel_contains(y, x) && (py.flags.blind < 1)
  2642.                 && (c_ptr->tl || c_ptr->pl)) {
  2643.                 print(tchar, y, x);
  2644.                 put_qio();    /* show object moving */
  2645. #ifdef MSDOS
  2646.                 delay(8 * delay_spd);    /* milliseconds */
  2647. #else
  2648.                 usleep(8000 * delay_spd);    /* useconds */
  2649. #endif
  2650.                 }
  2651.             }
  2652.             } else {
  2653.             flag = TRUE;
  2654.             drop_throw(oldy, oldx, &throw_obj);
  2655.             }
  2656.             oldy = y;
  2657.             oldx = x;
  2658.         }
  2659.         while (!flag);
  2660.         if (thits > 0) {   /* triple crossbow check -- not really needed */
  2661.             if (inventory[INVEN_WIELD].subval != 12) {
  2662.             (void)sprintf(out_val, "Keep shooting?");
  2663.             if (get_check(out_val)) {
  2664.                 desc_remain(item_val);
  2665.                 inven_throw(item_val, &throw_obj);
  2666.             } else
  2667.                 thits = 0;
  2668.             } else {
  2669.             desc_remain(item_val);
  2670.             inven_throw(item_val, &throw_obj);
  2671.             }
  2672.         }
  2673.  
  2674.                 /* If we're going to fire again, reroll damage for the
  2675.                    next missile. This makes each missile's damage more
  2676.                    random, AND it doesn't allow damage bonuses to accumulate!
  2677.                 */
  2678.         if (thits > 0) {
  2679.                     int dummy; /* ignore everything except tdam */
  2680.                     facts(&throw_obj, &dummy, &dummy, &tdam, &dummy, &dummy);
  2681.                 }
  2682.         }
  2683.     } /* EAM end loop over multiple shots */
  2684.     }
  2685. }
  2686.  
  2687.  
  2688. /* Make a bash attack on someone.                -CJS- Used to
  2689.  * be part of bash above. 
  2690.  */
  2691. static void 
  2692. py_bash(y, x)
  2693. int y, x;
  2694. {
  2695.     int                     monster, k, avg_max_hp, base_tohit, monptr;
  2696.     register creature_type *c_ptr;
  2697.     register monster_type  *m_ptr;
  2698.     vtype                   m_name, out_val;
  2699.  
  2700.     monster = cave[y][x].cptr;
  2701.     m_ptr = &m_list[monster];
  2702.     monptr = m_ptr->mptr;
  2703.     c_ptr = &c_list[monptr];
  2704.     m_ptr->csleep = 0;
  2705. /* Does the player know what he's fighting?       */
  2706.     if (!m_ptr->ml)
  2707.     (void)strcpy(m_name, "it");
  2708.     else {
  2709.     if (c_list[monptr].cdefense & UNIQUE)
  2710.         (void)sprintf(m_name, "%s", c_list[monptr].name);
  2711.     else
  2712.         (void)sprintf(m_name, "the %s", c_list[monptr].name);
  2713.     }
  2714.     base_tohit = py.stats.use_stat[A_STR] + inventory[INVEN_ARM].weight / 2
  2715.     + py.misc.wt / 10;
  2716.     if (!m_ptr->ml)
  2717.     base_tohit = (base_tohit / 2) - (py.stats.use_stat[A_DEX] * (BTH_PLUS_ADJ - 1))
  2718.         - (py.misc.lev * class_level_adj[py.misc.pclass][CLA_BTH] / 2);
  2719.  
  2720.     if (test_hit(base_tohit, (int)py.misc.lev,
  2721.          (int)py.stats.use_stat[A_DEX], (int)c_ptr->ac, CLA_BTH)) {
  2722.     (void)sprintf(out_val, "You hit %s.", m_name);
  2723.     msg_print(out_val);
  2724.     k = pdamroll(inventory[INVEN_ARM].damage);
  2725.     k = critical_blow((int)(inventory[INVEN_ARM].weight / 4
  2726.                 + py.stats.use_stat[A_STR]), 0, k, CLA_BTH);
  2727.     k += py.misc.wt / 60 + 3;
  2728.  
  2729.     if (k < 0)
  2730.         k = 0;           /* no neg damage! */
  2731.  
  2732.     /* See if we done it in.                     */
  2733.     if (mon_take_hit(monster, k, TRUE) >= 0) {
  2734.         if ((c_list[monptr].cdefense & (DEMON|UNDEAD|MINDLESS)) ||
  2735.         (c_list[monptr].cchar == 'E') ||
  2736.         (c_list[monptr].cchar == 'v') ||
  2737.         (c_list[monptr].cchar == 'g'))
  2738.         (void)sprintf(out_val, "You have destroyed %s.", m_name);
  2739.         else
  2740.         (void)sprintf(out_val, "You have slain %s.", m_name);
  2741.         msg_print(out_val);
  2742.         prt_experience();
  2743.     } else {
  2744.         m_name[0] = toupper((int)m_name[0]);    /* Capitalize */
  2745.     /* Can not stun Balrog */
  2746.         avg_max_hp = (c_ptr->cdefense & MAX_HP ?
  2747.               c_ptr->hd[0] * c_ptr->hd[1] :
  2748.               (c_ptr->hd[0] * (c_ptr->hd[1] + 1)) >> 1);
  2749.         if ((100 + randint(400) + randint(400))
  2750.         > (m_ptr->hp + avg_max_hp)) {
  2751.         m_ptr->stunned += randint(3) + 1;
  2752.         if (m_ptr->stunned > 24)
  2753.             m_ptr->stunned = 24;
  2754.         (void)sprintf(out_val, "%s appears stunned!", m_name);
  2755.         } else
  2756.         (void)sprintf(out_val, "%s ignores your bash!", m_name);
  2757.         msg_print(out_val);
  2758.     }
  2759.     } else {
  2760.     (void)sprintf(out_val, "You miss %s.", m_name);
  2761.     msg_print(out_val);
  2762.     }
  2763.     if (randint(150) > py.stats.use_stat[A_DEX]) {
  2764.     msg_print("You are off balance.");
  2765.     py.flags.paralysis = 1 + randint(2);
  2766.     }
  2767. }
  2768.  
  2769.  
  2770. /* Bash open a door or chest                -RAK-     */
  2771. /*
  2772.  * Note: Affected by strength and weight of character 
  2773.  *
  2774.  * For a closed door, p1 is positive if locked; negative if stuck. A disarm
  2775.  * spell unlocks and unjams doors! 
  2776.  *
  2777.  * For an open door, p1 is positive for a broken door. 
  2778.  *
  2779.  * A closed door can be opened - harder if locked. Any door might be bashed open
  2780.  * (and thereby broken). Bashing a door is (potentially) faster! You move
  2781.  * into the door way. To open a stuck door, it must be bashed. A closed door
  2782.  * can be jammed (which makes it stuck if previously locked). 
  2783.  *
  2784.  * Creatures can also open doors. A creature with open door ability will (if not
  2785.  * in the line of sight) move though a closed or secret door with no changes.
  2786.  * If in the line of sight, closed door are openned, & secret door revealed.
  2787.  * Whether in the line of sight or not, such a creature may unlock or unstick
  2788.  * a door. 
  2789.  *
  2790.  * A creature with no such ability will attempt to bash a non-secret door. 
  2791.  */
  2792. void 
  2793. bash()
  2794. {
  2795.     int                  y, x, dir, tmp;
  2796.     register cave_type  *c_ptr;
  2797.     register inven_type *t_ptr;
  2798. #ifdef TARGET
  2799.     int temp = target_mode; /* targetting will screw up get_dir, so we save
  2800.                    target_mode, then turn it off -CFT */
  2801. #endif
  2802.  
  2803.     y = char_row;
  2804.     x = char_col;
  2805. #ifdef TARGET
  2806.     target_mode = FALSE;
  2807. #endif
  2808.     if (get_dir(NULL, &dir)) {
  2809.     if (py.flags.confused > 0) {
  2810.         msg_print("You are confused.");
  2811.         do {
  2812.         dir = randint(9);
  2813.         }
  2814.         while (dir == 5);
  2815.     }
  2816.     (void)mmove(dir, &y, &x);
  2817.     c_ptr = &cave[y][x];
  2818.     if (c_ptr->cptr > 1) {
  2819.         if (py.flags.afraid > 0)
  2820.         msg_print("You are too afraid!");
  2821.         else
  2822.         py_bash(y, x);
  2823.     } else if (c_ptr->tptr != 0) {
  2824.         t_ptr = &t_list[c_ptr->tptr];
  2825.         if (t_ptr->tval == TV_CLOSED_DOOR) {
  2826.         count_msg_print("You smash into the door!");
  2827.         tmp = py.stats.use_stat[A_STR] + py.misc.wt / 2;
  2828.         /* Use (roughly) similar method as for monsters. */
  2829.         if (randint(tmp * (20 + MY_ABS(t_ptr->p1))) <
  2830.             10 * (tmp - MY_ABS(t_ptr->p1))) {
  2831.             msg_print("The door crashes open!");
  2832.             invcopy(&t_list[c_ptr->tptr], OBJ_OPEN_DOOR);
  2833.             t_ptr->p1 = 1 - randint(2);    /* 50% chance of breaking door */
  2834.             c_ptr->fval = CORR_FLOOR;
  2835.             if (py.flags.confused == 0)
  2836.             move_char(dir, FALSE);
  2837.             else
  2838.             lite_spot(y, x);
  2839.             check_view();
  2840.         } else if (randint(150) > py.stats.use_stat[A_DEX]) {
  2841.             msg_print("You are off-balance.");
  2842.             py.flags.paralysis = 1 + randint(2);
  2843.         } else if (command_count == 0)
  2844.             msg_print("The door holds firm.");
  2845.         } else if (t_ptr->tval == TV_CHEST) {
  2846.         if (randint(10) == 1) {
  2847.             msg_print("You have destroyed the chest and its contents!");
  2848.             t_ptr->index = OBJ_RUINED_CHEST;
  2849.             t_ptr->flags = 0;
  2850.         } else if ((CH_LOCKED & t_ptr->flags) && (randint(10) == 1)) {
  2851.             msg_print("The lock breaks open!");
  2852.             t_ptr->flags &= ~CH_LOCKED;
  2853.         } else
  2854.             count_msg_print("The chest holds firm.");
  2855.         } else
  2856.         /*
  2857.          * Can't give free turn, or else player could try directions
  2858.          * until he found invisible creature 
  2859.          */
  2860.         msg_print("You bash it, but nothing interesting happens.");
  2861.     } else {
  2862.         if (c_ptr->fval < MIN_CAVE_WALL)
  2863.         msg_print("You bash at empty space.");
  2864.         else
  2865.         /* same message for wall as for secret door */
  2866.         msg_print("You bash it, but nothing interesting happens.");
  2867.     }
  2868.     }
  2869. #ifdef TARGET
  2870.     target_mode = temp;
  2871. #endif
  2872. }
  2873.  
  2874.  
  2875. static const char *
  2876. look_mon_desc(mnum)
  2877. int mnum;
  2878. {
  2879.     monster_type *m = &m_list[mnum];
  2880.     int32         thp, tmax, perc;
  2881.     int8u         living;
  2882.  
  2883.     living = !((c_list[m->mptr].cdefense & (UNDEAD|DEMON)) ||
  2884.            ((c_list[m->mptr].cchar == 'E') ||
  2885.         (c_list[m->mptr].cchar == 'g') ||
  2886.         (c_list[m->mptr].cchar == 'v') ||
  2887.         (c_list[m->mptr].cchar == 'X')));
  2888.     
  2889.     if (m->maxhp == 0) {       /* then we're just going to fix it! -CFT */
  2890.     if ((c_list[m->mptr].cdefense & MAX_HP) || be_nasty)
  2891.         m->maxhp = max_hp(c_list[m->mptr].hd);
  2892.     else
  2893.         m->maxhp = pdamroll(c_list[m->mptr].hd);
  2894.     }
  2895.     if (m->hp > m->maxhp)
  2896.     m->hp = m->maxhp;
  2897.  
  2898.     if ((m->maxhp == 0) || (m->hp >= m->maxhp))    /* shouldn't ever need > -CFT */
  2899.     return (living ? "unhurt" : "undamaged");
  2900.     thp = (int32) m->hp;
  2901.     tmax = (int32) m->maxhp;
  2902.     perc = (int32) (thp * 100L) / tmax;
  2903.     if (perc > 60)
  2904.     return (living ? "somewhat wounded" : "somewhat damaged");
  2905.     if (perc > 25)
  2906.     return (living ? "wounded" : "damaged");
  2907.     if (perc > 10)
  2908.     return (living ? "badly wounded" : "badly damaged");
  2909.     return (living ? "almost dead" : "almost destroyed");
  2910. }
  2911.  
  2912. #ifdef TARGET
  2913. /* This targetting code stolen from Morgul -CFT */
  2914. /* Targetting routine                     CDW */
  2915. void
  2916. target()
  2917. {
  2918.     int monptr,exit,exit2;
  2919.     char query;
  2920.     vtype desc;
  2921.  
  2922.     exit = FALSE;
  2923.     exit2 = FALSE;
  2924.     if (py.flags.blind > 0)
  2925.     msg_print("You can't see anything to target!");
  2926.     /* Check monsters first */
  2927.     else {
  2928.     target_mode = FALSE;
  2929.     for (monptr = 0; (monptr<mfptr) && (!exit); monptr++) {
  2930.         if (m_list[monptr].cdis<MAX_SIGHT) {
  2931.         if ((m_list[monptr].ml)&&
  2932.             (los(char_row,char_col,m_list[monptr].fy,m_list[monptr].fx))) {
  2933.             move_cursor_relative(m_list[monptr].fy,m_list[monptr].fx);
  2934.             (void) sprintf(desc, "%s [(r)ecall] [(t)arget] [(l)ocation] [ESC quits]",
  2935.                    c_list[m_list[monptr].mptr].name);
  2936.             prt(desc,0,0);
  2937.             move_cursor_relative(m_list[monptr].fy,m_list[monptr].fx);
  2938.             query = inkey();
  2939.             while ((query == 'r')||(query == 'R')) {
  2940.             save_screen();
  2941.             query = roff_recall(m_list[monptr].mptr);
  2942.             restore_screen();
  2943.             move_cursor_relative(m_list[monptr].fy,m_list[monptr].fx);
  2944.             query = inkey();
  2945.             }
  2946.             switch (query) {
  2947.             case ESCAPE:
  2948.             exit = TRUE;
  2949.             exit2 = TRUE;
  2950.             break;
  2951.             case '.':    /* for NetHack players, '.' is used to select a target,
  2952.                    so I'm changing this... -CFT */
  2953.             case 't': case 'T':
  2954.             target_mode = TRUE;
  2955.             target_mon  = monptr;
  2956.             target_row  = m_list[monptr].fy;
  2957.             target_col  = m_list[monptr].fx;
  2958.             exit2 = TRUE;
  2959.             case 'l': case'L':
  2960.             exit = TRUE;
  2961.             default:
  2962.             break;
  2963.             }
  2964.         }
  2965.         }
  2966.     }
  2967.     if (exit2 == FALSE) {
  2968.         prt("Use cursor to designate target. [(t)arget]",0,0);
  2969.         target_row = char_row;
  2970.         target_col = char_col;
  2971.         for (exit = FALSE; exit==FALSE ;) {
  2972.         move_cursor_relative(target_row, target_col);
  2973.         query=inkey();
  2974.         if (rogue_like_commands==FALSE) {
  2975.             switch (query) {
  2976.             case '1':
  2977.             query = 'b';
  2978.             break;
  2979.             case '2':
  2980.             query = 'j';
  2981.             break;
  2982.             case '3':
  2983.             query = 'n';
  2984.             break;
  2985.             case '4':
  2986.             query = 'h';
  2987.             break;
  2988.             case '5':
  2989.             query = '.';
  2990.             case '6':
  2991.             query = 'l';
  2992.             break;
  2993.             case '7':
  2994.             query = 'y';
  2995.             break;
  2996.             case '8':
  2997.             query = 'k';
  2998.             break;
  2999.             case '9':
  3000.             query = 'u';
  3001.             break;
  3002.             default:
  3003.             break;
  3004.             }
  3005.         }
  3006.         switch (query) {
  3007.         case ESCAPE:
  3008.             case'q':
  3009.         case 'Q':
  3010.             exit = TRUE;
  3011.             break;
  3012.         case '.':    /* for NetHack players, '.' is used to select a target,
  3013.                    so I'm changing this... -CFT */
  3014.         case 't':
  3015.         case 'T':
  3016.             if (distance(char_row,char_col,target_row,target_col)>MAX_SIGHT)
  3017.             prt(
  3018.                 "Target beyond range. Use cursor to designate target. [(t)arget].",
  3019.                 0,0);
  3020.             else if (cave[target_row][target_col].fval>CORR_FLOOR)
  3021.             prt(
  3022.                 "Invalid target. Use cursor to designate target. [(t)arget].",
  3023.                 0,0);
  3024.             else {
  3025.             target_mode = TRUE;
  3026.             target_mon  = MAX_MALLOC;
  3027.             exit = TRUE;
  3028.             }
  3029.             break;
  3030.         case 'b':
  3031.             target_col--;
  3032.         case 'j':
  3033.             target_row++;
  3034.             break;
  3035.         case 'n':
  3036.             target_row++;
  3037.         case 'l':
  3038.             target_col++;
  3039.             break;
  3040.         case 'y':
  3041.             target_row--;
  3042.         case 'h':
  3043.             target_col--;
  3044.             break;
  3045.         case 'u':
  3046.             target_col++;
  3047.         case 'k':
  3048.             target_row--;
  3049.             break;
  3050.         default:
  3051.             break;
  3052.         }
  3053.         if ((target_col>MAX_WIDTH-2)||(target_col>panel_col_max))
  3054.             target_col--;
  3055.         else if ((target_col<1)||(target_col<panel_col_min))
  3056.             target_col++;
  3057.         if ((target_row>MAX_HEIGHT-2)||(target_row>panel_row_max))
  3058.             target_row--;
  3059.         else if ((target_row<1)||(target_row<panel_row_min))
  3060.             target_row++;
  3061.         
  3062.         }
  3063.     }
  3064.     if (target_mode==TRUE)
  3065.         msg_print("Target selected.");
  3066.     else
  3067.         msg_print("Aborting Target.");
  3068.     }
  3069. }
  3070.  
  3071. /* This targetting code stolen from Morgul -CFT */
  3072. /* Assuming target_mode == TRUE, returns if the position is the target.
  3073.                         CDW */
  3074. int
  3075. at_target(row,col)
  3076. int row, col;
  3077. {
  3078. /* don't ever assume a condition holds, especially when it's so easy to test for. -CFT */
  3079.     if (target_mode == FALSE)
  3080.     return FALSE;
  3081.  
  3082.     if ((row==target_row)&&(col==target_col))
  3083.     return(TRUE);
  3084.     else
  3085.     return(FALSE);
  3086. }
  3087. #endif /* TARGET */
  3088.  
  3089. void 
  3090. mmove2(y, x, sourcey, sourcex, desty, destx)
  3091. register int *y, *x;
  3092. int           sourcey, sourcex, desty, destx;
  3093. {
  3094.     int d_y, d_x, k, dist, max_dist, min_dist, shift;
  3095.  
  3096.     d_y = (*y < sourcey) ? sourcey - *y : *y - sourcey;
  3097.     d_x = (*x < sourcex) ? sourcex - *x : *x - sourcex;
  3098.     dist = (d_y > d_x) ? d_y : d_x;
  3099.     dist++;
  3100.     d_y = (desty < sourcey) ? sourcey - desty : desty - sourcey;
  3101.     d_x = (destx < sourcex) ? sourcex - destx : destx - sourcex;
  3102.     if (d_y > d_x) {
  3103.     max_dist = d_y;
  3104.     min_dist = d_x;
  3105.     } else {
  3106.     max_dist = d_x;
  3107.     min_dist = d_y;
  3108.     }
  3109.  
  3110.     for (k = 0, shift = max_dist >> 1; k < dist; k++, shift -= min_dist)
  3111.     shift = (shift > 0) ? shift : shift + max_dist;
  3112.     if (shift < 0)
  3113.     shift = 0;
  3114.  
  3115.     if (d_y > d_x) {
  3116.     d_y = (desty < sourcey) ? *y - 1 : *y + 1;
  3117.     if (shift)
  3118.         d_x = *x;
  3119.     else
  3120.         d_x = (destx < sourcex) ? *x - 1 : *x + 1;
  3121.     } else {
  3122.     d_x = (destx < sourcex) ? *x - 1 : *x + 1;
  3123.     if (shift)
  3124.         d_y = *y;
  3125.     else
  3126.         d_y = (desty < sourcey) ? *y - 1 : *y + 1;
  3127.     }
  3128.     *y = d_y;
  3129.     *x = d_x;
  3130. }
  3131.